diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt index 133c89eaf..83518664e 100644 --- a/src/SFML/Window/CMakeLists.txt +++ b/src/SFML/Window/CMakeLists.txt @@ -118,6 +118,10 @@ elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD OR SFML_OS_NETBSD) ${SRCROOT}/Unix/ClipboardImpl.cpp ${SRCROOT}/Unix/InputImpl.cpp ${SRCROOT}/Unix/InputImpl.hpp + ${SRCROOT}/Unix/KeyboardImpl.hpp + ${SRCROOT}/Unix/KeyboardImpl.cpp + ${SRCROOT}/Unix/KeySymToSFKeyMapping.hpp + ${SRCROOT}/Unix/KeySymToUnicodeMapping.hpp ${SRCROOT}/Unix/SensorImpl.cpp ${SRCROOT}/Unix/SensorImpl.hpp ${SRCROOT}/Unix/Display.cpp diff --git a/src/SFML/Window/Unix/InputImpl.cpp b/src/SFML/Window/Unix/InputImpl.cpp index dc0f38203..8d4b2ecfe 100644 --- a/src/SFML/Window/Unix/InputImpl.cpp +++ b/src/SFML/Window/Unix/InputImpl.cpp @@ -26,8 +26,9 @@ // Headers //////////////////////////////////////////////////////////// #include // important to be included first (conflict with None) -#include #include +#include +#include #include #include @@ -39,142 +40,38 @@ namespace priv //////////////////////////////////////////////////////////// bool InputImpl::isKeyPressed(Keyboard::Key key) { - // Get the corresponding X11 keysym - KeySym keysym = 0; - switch (key) - { - case Keyboard::LShift: keysym = XK_Shift_L; break; - case Keyboard::RShift: keysym = XK_Shift_R; break; - case Keyboard::LControl: keysym = XK_Control_L; break; - case Keyboard::RControl: keysym = XK_Control_R; break; - case Keyboard::LAlt: keysym = XK_Alt_L; break; - case Keyboard::RAlt: keysym = XK_Alt_R; break; - case Keyboard::LSystem: keysym = XK_Super_L; break; - case Keyboard::RSystem: keysym = XK_Super_R; break; - case Keyboard::Menu: keysym = XK_Menu; break; - case Keyboard::Escape: keysym = XK_Escape; break; - case Keyboard::Semicolon: keysym = XK_semicolon; break; - case Keyboard::Slash: keysym = XK_slash; break; - case Keyboard::Equal: keysym = XK_equal; break; - case Keyboard::Hyphen: keysym = XK_minus; break; - case Keyboard::LBracket: keysym = XK_bracketleft; break; - case Keyboard::RBracket: keysym = XK_bracketright; break; - case Keyboard::Comma: keysym = XK_comma; break; - case Keyboard::Period: keysym = XK_period; break; - case Keyboard::Quote: keysym = XK_apostrophe; break; - case Keyboard::Backslash: keysym = XK_backslash; break; - case Keyboard::Tilde: keysym = XK_grave; break; - case Keyboard::Space: keysym = XK_space; break; - case Keyboard::Enter: keysym = XK_Return; break; - case Keyboard::Backspace: keysym = XK_BackSpace; break; - case Keyboard::Tab: keysym = XK_Tab; break; - case Keyboard::PageUp: keysym = XK_Prior; break; - case Keyboard::PageDown: keysym = XK_Next; break; - case Keyboard::End: keysym = XK_End; break; - case Keyboard::Home: keysym = XK_Home; break; - case Keyboard::Insert: keysym = XK_Insert; break; - case Keyboard::Delete: keysym = XK_Delete; break; - case Keyboard::Add: keysym = XK_KP_Add; break; - case Keyboard::Subtract: keysym = XK_KP_Subtract; break; - case Keyboard::Multiply: keysym = XK_KP_Multiply; break; - case Keyboard::Divide: keysym = XK_KP_Divide; break; - case Keyboard::Pause: keysym = XK_Pause; break; - case Keyboard::F1: keysym = XK_F1; break; - case Keyboard::F2: keysym = XK_F2; break; - case Keyboard::F3: keysym = XK_F3; break; - case Keyboard::F4: keysym = XK_F4; break; - case Keyboard::F5: keysym = XK_F5; break; - case Keyboard::F6: keysym = XK_F6; break; - case Keyboard::F7: keysym = XK_F7; break; - case Keyboard::F8: keysym = XK_F8; break; - case Keyboard::F9: keysym = XK_F9; break; - case Keyboard::F10: keysym = XK_F10; break; - case Keyboard::F11: keysym = XK_F11; break; - case Keyboard::F12: keysym = XK_F12; break; - case Keyboard::F13: keysym = XK_F13; break; - case Keyboard::F14: keysym = XK_F14; break; - case Keyboard::F15: keysym = XK_F15; break; - case Keyboard::Left: keysym = XK_Left; break; - case Keyboard::Right: keysym = XK_Right; break; - case Keyboard::Up: keysym = XK_Up; break; - case Keyboard::Down: keysym = XK_Down; break; - case Keyboard::Numpad0: keysym = XK_KP_Insert; break; - case Keyboard::Numpad1: keysym = XK_KP_End; break; - case Keyboard::Numpad2: keysym = XK_KP_Down; break; - case Keyboard::Numpad3: keysym = XK_KP_Page_Down; break; - case Keyboard::Numpad4: keysym = XK_KP_Left; break; - case Keyboard::Numpad5: keysym = XK_KP_Begin; break; - case Keyboard::Numpad6: keysym = XK_KP_Right; break; - case Keyboard::Numpad7: keysym = XK_KP_Home; break; - case Keyboard::Numpad8: keysym = XK_KP_Up; break; - case Keyboard::Numpad9: keysym = XK_KP_Page_Up; break; - case Keyboard::A: keysym = XK_a; break; - case Keyboard::B: keysym = XK_b; break; - case Keyboard::C: keysym = XK_c; break; - case Keyboard::D: keysym = XK_d; break; - case Keyboard::E: keysym = XK_e; break; - case Keyboard::F: keysym = XK_f; break; - case Keyboard::G: keysym = XK_g; break; - case Keyboard::H: keysym = XK_h; break; - case Keyboard::I: keysym = XK_i; break; - case Keyboard::J: keysym = XK_j; break; - case Keyboard::K: keysym = XK_k; break; - case Keyboard::L: keysym = XK_l; break; - case Keyboard::M: keysym = XK_m; break; - case Keyboard::N: keysym = XK_n; break; - case Keyboard::O: keysym = XK_o; break; - case Keyboard::P: keysym = XK_p; break; - case Keyboard::Q: keysym = XK_q; break; - case Keyboard::R: keysym = XK_r; break; - case Keyboard::S: keysym = XK_s; break; - case Keyboard::T: keysym = XK_t; break; - case Keyboard::U: keysym = XK_u; break; - case Keyboard::V: keysym = XK_v; break; - case Keyboard::W: keysym = XK_w; break; - case Keyboard::X: keysym = XK_x; break; - case Keyboard::Y: keysym = XK_y; break; - case Keyboard::Z: keysym = XK_z; break; - case Keyboard::Num0: keysym = XK_0; break; - case Keyboard::Num1: keysym = XK_1; break; - case Keyboard::Num2: keysym = XK_2; break; - case Keyboard::Num3: keysym = XK_3; break; - case Keyboard::Num4: keysym = XK_4; break; - case Keyboard::Num5: keysym = XK_5; break; - case Keyboard::Num6: keysym = XK_6; break; - case Keyboard::Num7: keysym = XK_7; break; - case Keyboard::Num8: keysym = XK_8; break; - case Keyboard::Num9: keysym = XK_9; break; - default: keysym = 0; break; - } + return KeyboardImpl::isKeyPressed(key); +} - // Sanity checks - if (key < 0 || key >= sf::Keyboard::KeyCount) - return false; +//////////////////////////////////////////////////////////// +bool InputImpl::isKeyPressed(Keyboard::Scancode code) +{ + return KeyboardImpl::isKeyPressed(code); +} // Open a connection with the X server Display* display = OpenDisplay(); - // Convert to keycode - KeyCode keycode = XKeysymToKeycode(display, keysym); - if (keycode != 0) - { - // Get the whole keyboard state - char keys[32]; - XQueryKeymap(display, keys); +//////////////////////////////////////////////////////////// +Keyboard::Key InputImpl::localize(Keyboard::Scancode code) +{ + return KeyboardImpl::localize(code); +} // Close the connection with the X server CloseDisplay(display); - // Check our keycode - return (keys[keycode / 8] & (1 << (keycode % 8))) != 0; - } - else - { - // Close the connection with the X server - CloseDisplay(display); +//////////////////////////////////////////////////////////// +Keyboard::Scancode InputImpl::unlocalize(Keyboard::Key key) +{ + return KeyboardImpl::unlocalize(key); +} - return false; - } + +//////////////////////////////////////////////////////////// +String InputImpl::getDescription(Keyboard::Scancode code) +{ + return KeyboardImpl::getDescription(code); } diff --git a/src/SFML/Window/Unix/KeySymToSFKeyMapping.hpp b/src/SFML/Window/Unix/KeySymToSFKeyMapping.hpp new file mode 100644 index 000000000..5ef4f425a --- /dev/null +++ b/src/SFML/Window/Unix/KeySymToSFKeyMapping.hpp @@ -0,0 +1,282 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_KEYSYMTOSFKEYMAPPING_HPP +#define SFML_KEYSYMTOSFKEYMAPPING_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Convert X11 KeySym to sf::Keyboard::Key +/// +/// \param symbol X11 KeySym +/// +/// \return The corresponding sf::Keyboard::Key +/// +//////////////////////////////////////////////////////////// +inline Keyboard::Key keySymToSFKey(KeySym symbol) +{ + switch (symbol) + { + case XK_Shift_L: return Keyboard::LShift; + case XK_Shift_R: return Keyboard::RShift; + case XK_Control_L: return Keyboard::LControl; + case XK_Control_R: return Keyboard::RControl; + case XK_Alt_L: return Keyboard::LAlt; + case XK_Alt_R: return Keyboard::RAlt; + case XK_Super_L: return Keyboard::LSystem; + case XK_Super_R: return Keyboard::RSystem; + case XK_Menu: return Keyboard::Menu; + case XK_Escape: return Keyboard::Escape; + case XK_semicolon: return Keyboard::SemiColon; + case XK_slash: return Keyboard::Slash; + case XK_equal: return Keyboard::Equal; + case XK_minus: return Keyboard::Dash; + case XK_bracketleft: return Keyboard::LBracket; + case XK_bracketright: return Keyboard::RBracket; + case XK_comma: return Keyboard::Comma; + case XK_period: return Keyboard::Period; + case XK_apostrophe: return Keyboard::Quote; + case XK_backslash: return Keyboard::BackSlash; + case XK_grave: return Keyboard::Tilde; + case XK_space: return Keyboard::Space; + case XK_Return: return Keyboard::Return; + case XK_KP_Enter: return Keyboard::Return; + case XK_BackSpace: return Keyboard::BackSpace; + case XK_Tab: return Keyboard::Tab; + case XK_Prior: return Keyboard::PageUp; + case XK_Next: return Keyboard::PageDown; + case XK_End: return Keyboard::End; + case XK_Home: return Keyboard::Home; + case XK_Insert: return Keyboard::Insert; + case XK_Delete: return Keyboard::Delete; + case XK_KP_Add: return Keyboard::Add; + case XK_KP_Subtract: return Keyboard::Subtract; + case XK_KP_Multiply: return Keyboard::Multiply; + case XK_KP_Divide: return Keyboard::Divide; + case XK_Pause: return Keyboard::Pause; + case XK_F1: return Keyboard::F1; + case XK_F2: return Keyboard::F2; + case XK_F3: return Keyboard::F3; + case XK_F4: return Keyboard::F4; + case XK_F5: return Keyboard::F5; + case XK_F6: return Keyboard::F6; + case XK_F7: return Keyboard::F7; + case XK_F8: return Keyboard::F8; + case XK_F9: return Keyboard::F9; + case XK_F10: return Keyboard::F10; + case XK_F11: return Keyboard::F11; + case XK_F12: return Keyboard::F12; + case XK_F13: return Keyboard::F13; + case XK_F14: return Keyboard::F14; + case XK_F15: return Keyboard::F15; + case XK_Left: return Keyboard::Left; + case XK_Right: return Keyboard::Right; + case XK_Up: return Keyboard::Up; + case XK_Down: return Keyboard::Down; + case XK_KP_Insert: return Keyboard::Numpad0; + case XK_KP_End: return Keyboard::Numpad1; + case XK_KP_Down: return Keyboard::Numpad2; + case XK_KP_Page_Down: return Keyboard::Numpad3; + case XK_KP_Left: return Keyboard::Numpad4; + case XK_KP_Begin: return Keyboard::Numpad5; + case XK_KP_Right: return Keyboard::Numpad6; + case XK_KP_Home: return Keyboard::Numpad7; + case XK_KP_Up: return Keyboard::Numpad8; + case XK_KP_Page_Up: return Keyboard::Numpad9; + case XK_a: return Keyboard::A; + case XK_b: return Keyboard::B; + case XK_c: return Keyboard::C; + case XK_d: return Keyboard::D; + case XK_e: return Keyboard::E; + case XK_f: return Keyboard::F; + case XK_g: return Keyboard::G; + case XK_h: return Keyboard::H; + case XK_i: return Keyboard::I; + case XK_j: return Keyboard::J; + case XK_k: return Keyboard::K; + case XK_l: return Keyboard::L; + case XK_m: return Keyboard::M; + case XK_n: return Keyboard::N; + case XK_o: return Keyboard::O; + case XK_p: return Keyboard::P; + case XK_q: return Keyboard::Q; + case XK_r: return Keyboard::R; + case XK_s: return Keyboard::S; + case XK_t: return Keyboard::T; + case XK_u: return Keyboard::U; + case XK_v: return Keyboard::V; + case XK_w: return Keyboard::W; + case XK_x: return Keyboard::X; + case XK_y: return Keyboard::Y; + case XK_z: return Keyboard::Z; + case XK_0: return Keyboard::Num0; + case XK_1: return Keyboard::Num1; + case XK_2: return Keyboard::Num2; + case XK_3: return Keyboard::Num3; + case XK_4: return Keyboard::Num4; + case XK_5: return Keyboard::Num5; + case XK_6: return Keyboard::Num6; + case XK_7: return Keyboard::Num7; + case XK_8: return Keyboard::Num8; + case XK_9: return Keyboard::Num9; + } + + return Keyboard::Unknown; +} + + +//////////////////////////////////////////////////////////// +/// \brief Convert sf::Keyboard::Key to X11 KeySym +/// +/// \param key X11 sf::Keyboard::Key +/// +/// \return The corresponding X11 KeySym +/// +//////////////////////////////////////////////////////////// +inline KeySym SFKeyToKeySym(Keyboard::Key key) +{ + // Get the corresponding X11 keysym + KeySym keysym = NoSymbol; + switch (key) + { + case Keyboard::LShift: keysym = XK_Shift_L; break; + case Keyboard::RShift: keysym = XK_Shift_R; break; + case Keyboard::LControl: keysym = XK_Control_L; break; + case Keyboard::RControl: keysym = XK_Control_R; break; + case Keyboard::LAlt: keysym = XK_Alt_L; break; + case Keyboard::RAlt: keysym = XK_Alt_R; break; + case Keyboard::LSystem: keysym = XK_Super_L; break; + case Keyboard::RSystem: keysym = XK_Super_R; break; + case Keyboard::Menu: keysym = XK_Menu; break; + case Keyboard::Escape: keysym = XK_Escape; break; + case Keyboard::SemiColon: keysym = XK_semicolon; break; + case Keyboard::Slash: keysym = XK_slash; break; + case Keyboard::Equal: keysym = XK_equal; break; + case Keyboard::Dash: keysym = XK_minus; break; + case Keyboard::LBracket: keysym = XK_bracketleft; break; + case Keyboard::RBracket: keysym = XK_bracketright; break; + case Keyboard::Comma: keysym = XK_comma; break; + case Keyboard::Period: keysym = XK_period; break; + case Keyboard::Quote: keysym = XK_apostrophe; break; + case Keyboard::BackSlash: keysym = XK_backslash; break; + case Keyboard::Tilde: keysym = XK_grave; break; + case Keyboard::Space: keysym = XK_space; break; + case Keyboard::Return: keysym = XK_Return; break; + case Keyboard::BackSpace: keysym = XK_BackSpace; break; + case Keyboard::Tab: keysym = XK_Tab; break; + case Keyboard::PageUp: keysym = XK_Prior; break; + case Keyboard::PageDown: keysym = XK_Next; break; + case Keyboard::End: keysym = XK_End; break; + case Keyboard::Home: keysym = XK_Home; break; + case Keyboard::Insert: keysym = XK_Insert; break; + case Keyboard::Delete: keysym = XK_Delete; break; + case Keyboard::Add: keysym = XK_KP_Add; break; + case Keyboard::Subtract: keysym = XK_KP_Subtract; break; + case Keyboard::Multiply: keysym = XK_KP_Multiply; break; + case Keyboard::Divide: keysym = XK_KP_Divide; break; + case Keyboard::Pause: keysym = XK_Pause; break; + case Keyboard::F1: keysym = XK_F1; break; + case Keyboard::F2: keysym = XK_F2; break; + case Keyboard::F3: keysym = XK_F3; break; + case Keyboard::F4: keysym = XK_F4; break; + case Keyboard::F5: keysym = XK_F5; break; + case Keyboard::F6: keysym = XK_F6; break; + case Keyboard::F7: keysym = XK_F7; break; + case Keyboard::F8: keysym = XK_F8; break; + case Keyboard::F9: keysym = XK_F9; break; + case Keyboard::F10: keysym = XK_F10; break; + case Keyboard::F11: keysym = XK_F11; break; + case Keyboard::F12: keysym = XK_F12; break; + case Keyboard::F13: keysym = XK_F13; break; + case Keyboard::F14: keysym = XK_F14; break; + case Keyboard::F15: keysym = XK_F15; break; + case Keyboard::Left: keysym = XK_Left; break; + case Keyboard::Right: keysym = XK_Right; break; + case Keyboard::Up: keysym = XK_Up; break; + case Keyboard::Down: keysym = XK_Down; break; + case Keyboard::Numpad0: keysym = XK_KP_Insert; break; + case Keyboard::Numpad1: keysym = XK_KP_End; break; + case Keyboard::Numpad2: keysym = XK_KP_Down; break; + case Keyboard::Numpad3: keysym = XK_KP_Page_Down; break; + case Keyboard::Numpad4: keysym = XK_KP_Left; break; + case Keyboard::Numpad5: keysym = XK_KP_Begin; break; + case Keyboard::Numpad6: keysym = XK_KP_Right; break; + case Keyboard::Numpad7: keysym = XK_KP_Home; break; + case Keyboard::Numpad8: keysym = XK_KP_Up; break; + case Keyboard::Numpad9: keysym = XK_KP_Page_Up; break; + case Keyboard::A: keysym = XK_a; break; + case Keyboard::B: keysym = XK_b; break; + case Keyboard::C: keysym = XK_c; break; + case Keyboard::D: keysym = XK_d; break; + case Keyboard::E: keysym = XK_e; break; + case Keyboard::F: keysym = XK_f; break; + case Keyboard::G: keysym = XK_g; break; + case Keyboard::H: keysym = XK_h; break; + case Keyboard::I: keysym = XK_i; break; + case Keyboard::J: keysym = XK_j; break; + case Keyboard::K: keysym = XK_k; break; + case Keyboard::L: keysym = XK_l; break; + case Keyboard::M: keysym = XK_m; break; + case Keyboard::N: keysym = XK_n; break; + case Keyboard::O: keysym = XK_o; break; + case Keyboard::P: keysym = XK_p; break; + case Keyboard::Q: keysym = XK_q; break; + case Keyboard::R: keysym = XK_r; break; + case Keyboard::S: keysym = XK_s; break; + case Keyboard::T: keysym = XK_t; break; + case Keyboard::U: keysym = XK_u; break; + case Keyboard::V: keysym = XK_v; break; + case Keyboard::W: keysym = XK_w; break; + case Keyboard::X: keysym = XK_x; break; + case Keyboard::Y: keysym = XK_y; break; + case Keyboard::Z: keysym = XK_z; break; + case Keyboard::Num0: keysym = XK_0; break; + case Keyboard::Num1: keysym = XK_1; break; + case Keyboard::Num2: keysym = XK_2; break; + case Keyboard::Num3: keysym = XK_3; break; + case Keyboard::Num4: keysym = XK_4; break; + case Keyboard::Num5: keysym = XK_5; break; + case Keyboard::Num6: keysym = XK_6; break; + case Keyboard::Num7: keysym = XK_7; break; + case Keyboard::Num8: keysym = XK_8; break; + case Keyboard::Num9: keysym = XK_9; break; + } + return keysym; +} + +} // namespace priv + +} // namespace sf + +#endif // SFML_KEYSYMTOSFKEYMAPPING_HPP diff --git a/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp b/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp new file mode 100644 index 000000000..2ee95d8fb --- /dev/null +++ b/src/SFML/Window/Unix/KeySymToUnicodeMapping.hpp @@ -0,0 +1,1414 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2017 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_KEYSYMTOUNICODEMAPPING_HPP +#define SFML_KEYSYMTOUNICODEMAPPING_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include // sf::Uint32 +#include // KeySym + +namespace sf +{ +namespace priv +{ + +//////////////////////////////////////////////////////////// +/// \brief Converts a KeySym to UTF-32 +/// +/// This code was autogenerated from the following table: +/// https://www.cl.cam.ac.uk/~mgk25/ucs/keysyms.txt +/// +/// \param keysym keysym to be converted +/// \return corresponding UTF-32 +//////////////////////////////////////////////////////////// +inline Uint32 keysymToUnicode(KeySym keysym) +{ + switch (keysym) + { + case 0xff08: return 0x0008; // BackSpace + case 0xff89: return 0x0009; // KP_Tab + case 0xff09: return 0x0009; // Tab + case 0xff0a: return 0x000a; // Linefeed + case 0xff0b: return 0x000b; // Clear + case 0xff8d: return 0x000d; // KP_Enter + case 0xff0d: return 0x000d; // Return + case 0xff13: return 0x0013; // Pause + case 0xff14: return 0x0014; // Scroll_Lock + case 0xff15: return 0x0015; // Sys_Req + case 0xff1b: return 0x001b; // Escape + case 0xff80: return 0x0020; // KP_Space + case 0x0020: return 0x0020; // space + case 0x0021: return 0x0021; // exclam + case 0x0022: return 0x0022; // quotedbl + case 0x0023: return 0x0023; // numbersign + case 0x0024: return 0x0024; // dollar + case 0x0025: return 0x0025; // percent + case 0x0026: return 0x0026; // ampersand + case 0x0027: return 0x0027; // quoteright + case 0x14a5: return 0x0028; // Armenian_parenleft + case 0x0028: return 0x0028; // parenleft + case 0x14a4: return 0x0029; // Armenian_parenright + case 0x0029: return 0x0029; // parenright + case 0xffaa: return 0x002a; // KP_Multiply + case 0x002a: return 0x002a; // asterisk + case 0xffab: return 0x002b; // KP_Add + case 0x002b: return 0x002b; // plus + case 0x14ab: return 0x002c; // Armenian_comma + case 0xffac: return 0x002c; // KP_Separator + case 0x002c: return 0x002c; // comma + case 0xffad: return 0x002d; // KP_Subtract + case 0x002d: return 0x002d; // minus + case 0x14a9: return 0x002e; // Armenian_mijaket + case 0xffae: return 0x002e; // KP_Decimal + case 0x0abd: return 0x002e; // decimalpoint + case 0x002e: return 0x002e; // period + case 0xffaf: return 0x002f; // KP_Divide + case 0x002f: return 0x002f; // slash + case 0x0030: return 0x0030; // 0 + case 0xffb0: return 0x0030; // KP_0 + case 0x0031: return 0x0031; // 1 + case 0xffb1: return 0x0031; // KP_1 + case 0x0032: return 0x0032; // 2 + case 0xffb2: return 0x0032; // KP_2 + case 0x0033: return 0x0033; // 3 + case 0xffb3: return 0x0033; // KP_3 + case 0x0034: return 0x0034; // 4 + case 0xffb4: return 0x0034; // KP_4 + case 0x0035: return 0x0035; // 5 + case 0xffb5: return 0x0035; // KP_5 + case 0x0036: return 0x0036; // 6 + case 0xffb6: return 0x0036; // KP_6 + case 0x0037: return 0x0037; // 7 + case 0xffb7: return 0x0037; // KP_7 + case 0x0038: return 0x0038; // 8 + case 0xffb8: return 0x0038; // KP_8 + case 0x0039: return 0x0039; // 9 + case 0xffb9: return 0x0039; // KP_9 + case 0x003a: return 0x003a; // colon + case 0x003b: return 0x003b; // semicolon + case 0x0ba3: return 0x003c; // leftcaret + case 0x003c: return 0x003c; // less + case 0xffbd: return 0x003d; // KP_Equal + case 0x003d: return 0x003d; // equal + case 0x003e: return 0x003e; // greater + case 0x0ba6: return 0x003e; // rightcaret + case 0x003f: return 0x003f; // question + case 0x0040: return 0x0040; // at + case 0x0041: return 0x0041; // A + case 0x0042: return 0x0042; // B + case 0x0043: return 0x0043; // C + case 0x0044: return 0x0044; // D + case 0x0045: return 0x0045; // E + case 0x0046: return 0x0046; // F + case 0x0047: return 0x0047; // G + case 0x0048: return 0x0048; // H + case 0x0049: return 0x0049; // I + case 0x004a: return 0x004a; // J + case 0x004b: return 0x004b; // K + case 0x004c: return 0x004c; // L + case 0x004d: return 0x004d; // M + case 0x004e: return 0x004e; // N + case 0x004f: return 0x004f; // O + case 0x0050: return 0x0050; // P + case 0x0051: return 0x0051; // Q + case 0x0052: return 0x0052; // R + case 0x0053: return 0x0053; // S + case 0x0054: return 0x0054; // T + case 0x0055: return 0x0055; // U + case 0x0056: return 0x0056; // V + case 0x0057: return 0x0057; // W + case 0x0058: return 0x0058; // X + case 0x0059: return 0x0059; // Y + case 0x005a: return 0x005a; // Z + case 0x005b: return 0x005b; // bracketleft + case 0x005c: return 0x005c; // backslash + case 0x005d: return 0x005d; // bracketright + case 0x005e: return 0x005e; // asciicircum + case 0x0bc6: return 0x005f; // underbar + case 0x005f: return 0x005f; // underscore + case 0x0060: return 0x0060; // quoteleft + case 0x0061: return 0x0061; // a + case 0x0062: return 0x0062; // b + case 0x0063: return 0x0063; // c + case 0x0064: return 0x0064; // d + case 0x0065: return 0x0065; // e + case 0x0066: return 0x0066; // f + case 0x0067: return 0x0067; // g + case 0x0068: return 0x0068; // h + case 0x0069: return 0x0069; // i + case 0x006a: return 0x006a; // j + case 0x006b: return 0x006b; // k + case 0x006c: return 0x006c; // l + case 0x006d: return 0x006d; // m + case 0x006e: return 0x006e; // n + case 0x006f: return 0x006f; // o + case 0x0070: return 0x0070; // p + case 0x0071: return 0x0071; // q + case 0x0072: return 0x0072; // r + case 0x0073: return 0x0073; // s + case 0x0074: return 0x0074; // t + case 0x0075: return 0x0075; // u + case 0x0076: return 0x0076; // v + case 0x0077: return 0x0077; // w + case 0x0078: return 0x0078; // x + case 0x0079: return 0x0079; // y + case 0x007a: return 0x007a; // z + case 0x007b: return 0x007b; // braceleft + case 0x007c: return 0x007c; // bar + case 0x007d: return 0x007d; // braceright + case 0x007e: return 0x007e; // asciitilde + case 0x00a0: return 0x00a0; // nobreakspace + case 0x00a1: return 0x00a1; // exclamdown + case 0x00a2: return 0x00a2; // cent + case 0x00a3: return 0x00a3; // sterling + case 0x00a4: return 0x00a4; // currency + case 0x00a5: return 0x00a5; // yen + case 0x00a6: return 0x00a6; // brokenbar + case 0x14ff: return 0x00a7; // Armenian_section_sign + case 0x00a7: return 0x00a7; // section + case 0x00a8: return 0x00a8; // diaeresis + case 0x00a9: return 0x00a9; // copyright + case 0x00aa: return 0x00aa; // ordfeminine + case 0x14a7: return 0x00ab; // Armenian_guillemotleft + case 0x00ab: return 0x00ab; // guillemotleft + case 0x00ac: return 0x00ac; // notsign + case 0x00ad: return 0x00ad; // hyphen + case 0x00ae: return 0x00ae; // registered + case 0x00af: return 0x00af; // macron + case 0x0bc0: return 0x00af; // overbar + case 0x00b0: return 0x00b0; // degree + case 0x00b1: return 0x00b1; // plusminus + case 0x00b2: return 0x00b2; // twosuperior + case 0x00b3: return 0x00b3; // threesuperior + case 0x00b4: return 0x00b4; // acute + case 0x00b5: return 0x00b5; // mu + case 0x00b6: return 0x00b6; // paragraph + case 0x00b7: return 0x00b7; // periodcentered + case 0x00b8: return 0x00b8; // cedilla + case 0x00b9: return 0x00b9; // onesuperior + case 0x00ba: return 0x00ba; // masculine + case 0x14a6: return 0x00bb; // Armenian_guillemotright + case 0x00bb: return 0x00bb; // guillemotright + case 0x00bc: return 0x00bc; // onequarter + case 0x00bd: return 0x00bd; // onehalf + case 0x00be: return 0x00be; // threequarters + case 0x00bf: return 0x00bf; // questiondown + case 0x00c0: return 0x00c0; // Agrave + case 0x00c1: return 0x00c1; // Aacute + case 0x00c2: return 0x00c2; // Acircumflex + case 0x00c3: return 0x00c3; // Atilde + case 0x00c4: return 0x00c4; // Adiaeresis + case 0x00c5: return 0x00c5; // Aring + case 0x00c6: return 0x00c6; // AE + case 0x00c7: return 0x00c7; // Ccedilla + case 0x00c8: return 0x00c8; // Egrave + case 0x00c9: return 0x00c9; // Eacute + case 0x00ca: return 0x00ca; // Ecircumflex + case 0x00cb: return 0x00cb; // Ediaeresis + case 0x00cc: return 0x00cc; // Igrave + case 0x00cd: return 0x00cd; // Iacute + case 0x00ce: return 0x00ce; // Icircumflex + case 0x00cf: return 0x00cf; // Idiaeresis + case 0x00d0: return 0x00d0; // Eth + case 0x00d1: return 0x00d1; // Ntilde + case 0x00d2: return 0x00d2; // Ograve + case 0x00d3: return 0x00d3; // Oacute + case 0x00d4: return 0x00d4; // Ocircumflex + case 0x00d5: return 0x00d5; // Otilde + case 0x00d6: return 0x00d6; // Odiaeresis + case 0x00d7: return 0x00d7; // multiply + case 0x00d8: return 0x00d8; // Ooblique + case 0x00d9: return 0x00d9; // Ugrave + case 0x00da: return 0x00da; // Uacute + case 0x00db: return 0x00db; // Ucircumflex + case 0x00dc: return 0x00dc; // Udiaeresis + case 0x00dd: return 0x00dd; // Yacute + case 0x00de: return 0x00de; // Thorn + case 0x00df: return 0x00df; // ssharp + case 0x00e0: return 0x00e0; // agrave + case 0x00e1: return 0x00e1; // aacute + case 0x00e2: return 0x00e2; // acircumflex + case 0x00e3: return 0x00e3; // atilde + case 0x00e4: return 0x00e4; // adiaeresis + case 0x00e5: return 0x00e5; // aring + case 0x00e6: return 0x00e6; // ae + case 0x00e7: return 0x00e7; // ccedilla + case 0x00e8: return 0x00e8; // egrave + case 0x00e9: return 0x00e9; // eacute + case 0x00ea: return 0x00ea; // ecircumflex + case 0x00eb: return 0x00eb; // ediaeresis + case 0x00ec: return 0x00ec; // igrave + case 0x00ed: return 0x00ed; // iacute + case 0x00ee: return 0x00ee; // icircumflex + case 0x00ef: return 0x00ef; // idiaeresis + case 0x00f0: return 0x00f0; // eth + case 0x00f1: return 0x00f1; // ntilde + case 0x00f2: return 0x00f2; // ograve + case 0x00f3: return 0x00f3; // oacute + case 0x00f4: return 0x00f4; // ocircumflex + case 0x00f5: return 0x00f5; // otilde + case 0x00f6: return 0x00f6; // odiaeresis + case 0x00f7: return 0x00f7; // division + case 0x00f8: return 0x00f8; // oslash + case 0x00f9: return 0x00f9; // ugrave + case 0x00fa: return 0x00fa; // uacute + case 0x00fb: return 0x00fb; // ucircumflex + case 0x00fc: return 0x00fc; // udiaeresis + case 0x00fd: return 0x00fd; // yacute + case 0x00fe: return 0x00fe; // thorn + case 0x00ff: return 0x00ff; // ydiaeresis + case 0x03c0: return 0x0100; // Amacron + case 0x03e0: return 0x0101; // amacron + case 0x01c3: return 0x0102; // Abreve + case 0x01e3: return 0x0103; // abreve + case 0x01a1: return 0x0104; // Aogonek + case 0x01b1: return 0x0105; // aogonek + case 0x01c6: return 0x0106; // Cacute + case 0x01e6: return 0x0107; // cacute + case 0x02c6: return 0x0108; // Ccircumflex + case 0x02e6: return 0x0109; // ccircumflex + case 0x02c5: return 0x010a; // Cabovedot + case 0x02e5: return 0x010b; // cabovedot + case 0x01c8: return 0x010c; // Ccaron + case 0x01e8: return 0x010d; // ccaron + case 0x01cf: return 0x010e; // Dcaron + case 0x01ef: return 0x010f; // dcaron + case 0x01d0: return 0x0110; // Dstroke + case 0x01f0: return 0x0111; // dstroke + case 0x03aa: return 0x0112; // Emacron + case 0x03ba: return 0x0113; // emacron + case 0x03cc: return 0x0116; // Eabovedot + case 0x03ec: return 0x0117; // eabovedot + case 0x01ca: return 0x0118; // Eogonek + case 0x01ea: return 0x0119; // eogonek + case 0x01cc: return 0x011a; // Ecaron + case 0x01ec: return 0x011b; // ecaron + case 0x02d8: return 0x011c; // Gcircumflex + case 0x02f8: return 0x011d; // gcircumflex + case 0x02ab: return 0x011e; // Gbreve + case 0x02bb: return 0x011f; // gbreve + case 0x02d5: return 0x0120; // Gabovedot + case 0x02f5: return 0x0121; // gabovedot + case 0x03ab: return 0x0122; // Gcedilla + case 0x03bb: return 0x0123; // gcedilla + case 0x02a6: return 0x0124; // Hcircumflex + case 0x02b6: return 0x0125; // hcircumflex + case 0x02a1: return 0x0126; // Hstroke + case 0x02b1: return 0x0127; // hstroke + case 0x03a5: return 0x0128; // Itilde + case 0x03b5: return 0x0129; // itilde + case 0x03cf: return 0x012a; // Imacron + case 0x03ef: return 0x012b; // imacron + case 0x16a6: return 0x012c; // Ibreve + case 0x16b6: return 0x012d; // ibreve + case 0x03c7: return 0x012e; // Iogonek + case 0x03e7: return 0x012f; // iogonek + case 0x02a9: return 0x0130; // Iabovedot + case 0x02b9: return 0x0131; // idotless + case 0x02ac: return 0x0134; // Jcircumflex + case 0x02bc: return 0x0135; // jcircumflex + case 0x03d3: return 0x0136; // Kcedilla + case 0x03f3: return 0x0137; // kcedilla + case 0x03a2: return 0x0138; // kra + case 0x01c5: return 0x0139; // Lacute + case 0x01e5: return 0x013a; // lacute + case 0x03a6: return 0x013b; // Lcedilla + case 0x03b6: return 0x013c; // lcedilla + case 0x01a5: return 0x013d; // Lcaron + case 0x01b5: return 0x013e; // lcaron + case 0x01a3: return 0x0141; // Lstroke + case 0x01b3: return 0x0142; // lstroke + case 0x01d1: return 0x0143; // Nacute + case 0x01f1: return 0x0144; // nacute + case 0x03d1: return 0x0145; // Ncedilla + case 0x03f1: return 0x0146; // ncedilla + case 0x01d2: return 0x0147; // Ncaron + case 0x01f2: return 0x0148; // ncaron + case 0x03bd: return 0x014a; // ENG + case 0x03bf: return 0x014b; // eng + case 0x03d2: return 0x014c; // Omacron + case 0x03f2: return 0x014d; // omacron + case 0x01d5: return 0x0150; // Odoubleacute + case 0x01f5: return 0x0151; // odoubleacute + case 0x13bc: return 0x0152; // OE + case 0x13bd: return 0x0153; // oe + case 0x01c0: return 0x0154; // Racute + case 0x01e0: return 0x0155; // racute + case 0x03a3: return 0x0156; // Rcedilla + case 0x03b3: return 0x0157; // rcedilla + case 0x01d8: return 0x0158; // Rcaron + case 0x01f8: return 0x0159; // rcaron + case 0x01a6: return 0x015a; // Sacute + case 0x01b6: return 0x015b; // sacute + case 0x02de: return 0x015c; // Scircumflex + case 0x02fe: return 0x015d; // scircumflex + case 0x01aa: return 0x015e; // Scedilla + case 0x01ba: return 0x015f; // scedilla + case 0x01a9: return 0x0160; // Scaron + case 0x01b9: return 0x0161; // scaron + case 0x01de: return 0x0162; // Tcedilla + case 0x01fe: return 0x0163; // tcedilla + case 0x01ab: return 0x0164; // Tcaron + case 0x01bb: return 0x0165; // tcaron + case 0x03ac: return 0x0166; // Tslash + case 0x03bc: return 0x0167; // tslash + case 0x03dd: return 0x0168; // Utilde + case 0x03fd: return 0x0169; // utilde + case 0x03de: return 0x016a; // Umacron + case 0x03fe: return 0x016b; // umacron + case 0x02dd: return 0x016c; // Ubreve + case 0x02fd: return 0x016d; // ubreve + case 0x01d9: return 0x016e; // Uring + case 0x01f9: return 0x016f; // uring + case 0x01db: return 0x0170; // Udoubleacute + case 0x01fb: return 0x0171; // udoubleacute + case 0x03d9: return 0x0172; // Uogonek + case 0x03f9: return 0x0173; // uogonek + case 0x12d0: return 0x0174; // Wcircumflex + case 0x12f0: return 0x0175; // wcircumflex + case 0x12de: return 0x0176; // Ycircumflex + case 0x12fe: return 0x0177; // ycircumflex + case 0x13be: return 0x0178; // Ydiaeresis + case 0x01ac: return 0x0179; // Zacute + case 0x01bc: return 0x017a; // zacute + case 0x01af: return 0x017b; // Zabovedot + case 0x01bf: return 0x017c; // zabovedot + case 0x01ae: return 0x017d; // Zcaron + case 0x01be: return 0x017e; // zcaron + case 0x16c6: return 0x018f; // SCHWA + case 0x08f6: return 0x0192; // function + case 0x16af: return 0x019f; // Obarred + case 0x1efa: return 0x01a0; // Ohorn + case 0x1efb: return 0x01a1; // ohorn + case 0x1efc: return 0x01af; // Uhorn + case 0x1efd: return 0x01b0; // uhorn + case 0x16a9: return 0x01b5; // Zstroke + case 0x16b9: return 0x01b6; // zstroke + case 0x16bd: return 0x01d2; // ocaron + case 0x16aa: return 0x01e6; // Gcaron + case 0x16ba: return 0x01e7; // gcaron + case 0x16f6: return 0x0259; // schwa + case 0x16bf: return 0x0275; // obarred + case 0x01b7: return 0x02c7; // caron + case 0x01a2: return 0x02d8; // breve + case 0x01ff: return 0x02d9; // abovedot + case 0x01b2: return 0x02db; // ogonek + case 0x01bd: return 0x02dd; // doubleacute + case 0x1ef2: return 0x0300; // combining_grave + case 0xfe50: return 0x0300; // dead_grave + case 0x1ef3: return 0x0301; // combining_acute + case 0xfe51: return 0x0301; // dead_acute + case 0xfe52: return 0x0302; // dead_circumflex + case 0x1e9f: return 0x0303; // combining_tilde + case 0xfe53: return 0x0303; // dead_tilde + case 0xfe54: return 0x0304; // dead_macron + case 0xfe55: return 0x0306; // dead_breve + case 0xfe56: return 0x0307; // dead_abovedot + case 0xfe57: return 0x0308; // dead_diaeresis + case 0x1efe: return 0x0309; // combining_hook + case 0xfe61: return 0x0309; // dead_hook + case 0xfe58: return 0x030a; // dead_abovering + case 0xfe59: return 0x030b; // dead_doubleacute + case 0xfe5a: return 0x030c; // dead_caron + case 0xfe62: return 0x031b; // dead_horn + case 0x1eff: return 0x0323; // combining_belowdot + case 0xfe60: return 0x0323; // dead_belowdot + case 0xfe5b: return 0x0327; // dead_cedilla + case 0xfe5c: return 0x0328; // dead_ogonek + case 0xfe5d: return 0x0345; // dead_iota + case 0x07ae: return 0x0385; // Greek_accentdieresis + case 0x07a1: return 0x0386; // Greek_ALPHAaccent + case 0x07a2: return 0x0388; // Greek_EPSILONaccent + case 0x07a3: return 0x0389; // Greek_ETAaccent + case 0x07a4: return 0x038a; // Greek_IOTAaccent + case 0x07a7: return 0x038c; // Greek_OMICRONaccent + case 0x07a8: return 0x038e; // Greek_UPSILONaccent + case 0x07ab: return 0x038f; // Greek_OMEGAaccent + case 0x07b6: return 0x0390; // Greek_iotaaccentdieresis + case 0x07c1: return 0x0391; // Greek_ALPHA + case 0x07c2: return 0x0392; // Greek_BETA + case 0x07c3: return 0x0393; // Greek_GAMMA + case 0x07c4: return 0x0394; // Greek_DELTA + case 0x07c5: return 0x0395; // Greek_EPSILON + case 0x07c6: return 0x0396; // Greek_ZETA + case 0x07c7: return 0x0397; // Greek_ETA + case 0x07c8: return 0x0398; // Greek_THETA + case 0x07c9: return 0x0399; // Greek_IOTA + case 0x07ca: return 0x039a; // Greek_KAPPA + case 0x07cb: return 0x039b; // Greek_LAMDA + case 0x07cc: return 0x039c; // Greek_MU + case 0x07cd: return 0x039d; // Greek_NU + case 0x07ce: return 0x039e; // Greek_XI + case 0x07cf: return 0x039f; // Greek_OMICRON + case 0x07d0: return 0x03a0; // Greek_PI + case 0x07d1: return 0x03a1; // Greek_RHO + case 0x07d2: return 0x03a3; // Greek_SIGMA + case 0x07d4: return 0x03a4; // Greek_TAU + case 0x07d5: return 0x03a5; // Greek_UPSILON + case 0x07d6: return 0x03a6; // Greek_PHI + case 0x07d7: return 0x03a7; // Greek_CHI + case 0x07d8: return 0x03a8; // Greek_PSI + case 0x07d9: return 0x03a9; // Greek_OMEGA + case 0x07a5: return 0x03aa; // Greek_IOTAdiaeresis + case 0x07a9: return 0x03ab; // Greek_UPSILONdieresis + case 0x07b1: return 0x03ac; // Greek_alphaaccent + case 0x07b2: return 0x03ad; // Greek_epsilonaccent + case 0x07b3: return 0x03ae; // Greek_etaaccent + case 0x07b4: return 0x03af; // Greek_iotaaccent + case 0x07ba: return 0x03b0; // Greek_upsilonaccentdieresis + case 0x07e1: return 0x03b1; // Greek_alpha + case 0x07e2: return 0x03b2; // Greek_beta + case 0x07e3: return 0x03b3; // Greek_gamma + case 0x07e4: return 0x03b4; // Greek_delta + case 0x07e5: return 0x03b5; // Greek_epsilon + case 0x07e6: return 0x03b6; // Greek_zeta + case 0x07e7: return 0x03b7; // Greek_eta + case 0x07e8: return 0x03b8; // Greek_theta + case 0x07e9: return 0x03b9; // Greek_iota + case 0x07ea: return 0x03ba; // Greek_kappa + case 0x07eb: return 0x03bb; // Greek_lambda + case 0x07ec: return 0x03bc; // Greek_mu + case 0x07ed: return 0x03bd; // Greek_nu + case 0x07ee: return 0x03be; // Greek_xi + case 0x07ef: return 0x03bf; // Greek_omicron + case 0x07f0: return 0x03c0; // Greek_pi + case 0x07f1: return 0x03c1; // Greek_rho + case 0x07f3: return 0x03c2; // Greek_finalsmallsigma + case 0x07f2: return 0x03c3; // Greek_sigma + case 0x07f4: return 0x03c4; // Greek_tau + case 0x07f5: return 0x03c5; // Greek_upsilon + case 0x07f6: return 0x03c6; // Greek_phi + case 0x07f7: return 0x03c7; // Greek_chi + case 0x07f8: return 0x03c8; // Greek_psi + case 0x07f9: return 0x03c9; // Greek_omega + case 0x07b5: return 0x03ca; // Greek_iotadieresis + case 0x07b9: return 0x03cb; // Greek_upsilondieresis + case 0x07b7: return 0x03cc; // Greek_omicronaccent + case 0x07b8: return 0x03cd; // Greek_upsilonaccent + case 0x07bb: return 0x03ce; // Greek_omegaaccent + case 0x06b3: return 0x0401; // Cyrillic_IO + case 0x06b1: return 0x0402; // Serbian_DJE + case 0x06b2: return 0x0403; // Macedonia_GJE + case 0x06b4: return 0x0404; // Ukrainian_IE + case 0x06b5: return 0x0405; // Macedonia_DSE + case 0x06b6: return 0x0406; // Ukrainian_I + case 0x06b7: return 0x0407; // Ukrainian_YI + case 0x06b8: return 0x0408; // Cyrillic_JE + case 0x06b9: return 0x0409; // Cyrillic_LJE + case 0x06ba: return 0x040a; // Cyrillic_NJE + case 0x06bb: return 0x040b; // Serbian_TSHE + case 0x06bc: return 0x040c; // Macedonia_KJE + case 0x06be: return 0x040e; // Byelorussian_SHORTU + case 0x06bf: return 0x040f; // Cyrillic_DZHE + case 0x06e1: return 0x0410; // Cyrillic_A + case 0x06e2: return 0x0411; // Cyrillic_BE + case 0x06f7: return 0x0412; // Cyrillic_VE + case 0x06e7: return 0x0413; // Cyrillic_GHE + case 0x06e4: return 0x0414; // Cyrillic_DE + case 0x06e5: return 0x0415; // Cyrillic_IE + case 0x06f6: return 0x0416; // Cyrillic_ZHE + case 0x06fa: return 0x0417; // Cyrillic_ZE + case 0x06e9: return 0x0418; // Cyrillic_I + case 0x06ea: return 0x0419; // Cyrillic_SHORTI + case 0x06eb: return 0x041a; // Cyrillic_KA + case 0x06ec: return 0x041b; // Cyrillic_EL + case 0x06ed: return 0x041c; // Cyrillic_EM + case 0x06ee: return 0x041d; // Cyrillic_EN + case 0x06ef: return 0x041e; // Cyrillic_O + case 0x06f0: return 0x041f; // Cyrillic_PE + case 0x06f2: return 0x0420; // Cyrillic_ER + case 0x06f3: return 0x0421; // Cyrillic_ES + case 0x06f4: return 0x0422; // Cyrillic_TE + case 0x06f5: return 0x0423; // Cyrillic_U + case 0x06e6: return 0x0424; // Cyrillic_EF + case 0x06e8: return 0x0425; // Cyrillic_HA + case 0x06e3: return 0x0426; // Cyrillic_TSE + case 0x06fe: return 0x0427; // Cyrillic_CHE + case 0x06fb: return 0x0428; // Cyrillic_SHA + case 0x06fd: return 0x0429; // Cyrillic_SHCHA + case 0x06ff: return 0x042a; // Cyrillic_HARDSIGN + case 0x06f9: return 0x042b; // Cyrillic_YERU + case 0x06f8: return 0x042c; // Cyrillic_SOFTSIGN + case 0x06fc: return 0x042d; // Cyrillic_E + case 0x06e0: return 0x042e; // Cyrillic_YU + case 0x06f1: return 0x042f; // Cyrillic_YA + case 0x06c1: return 0x0430; // Cyrillic_a + case 0x06c2: return 0x0431; // Cyrillic_be + case 0x06d7: return 0x0432; // Cyrillic_ve + case 0x06c7: return 0x0433; // Cyrillic_ghe + case 0x06c4: return 0x0434; // Cyrillic_de + case 0x06c5: return 0x0435; // Cyrillic_ie + case 0x06d6: return 0x0436; // Cyrillic_zhe + case 0x06da: return 0x0437; // Cyrillic_ze + case 0x06c9: return 0x0438; // Cyrillic_i + case 0x06ca: return 0x0439; // Cyrillic_shorti + case 0x06cb: return 0x043a; // Cyrillic_ka + case 0x06cc: return 0x043b; // Cyrillic_el + case 0x06cd: return 0x043c; // Cyrillic_em + case 0x06ce: return 0x043d; // Cyrillic_en + case 0x06cf: return 0x043e; // Cyrillic_o + case 0x06d0: return 0x043f; // Cyrillic_pe + case 0x06d2: return 0x0440; // Cyrillic_er + case 0x06d3: return 0x0441; // Cyrillic_es + case 0x06d4: return 0x0442; // Cyrillic_te + case 0x06d5: return 0x0443; // Cyrillic_u + case 0x06c6: return 0x0444; // Cyrillic_ef + case 0x06c8: return 0x0445; // Cyrillic_ha + case 0x06c3: return 0x0446; // Cyrillic_tse + case 0x06de: return 0x0447; // Cyrillic_che + case 0x06db: return 0x0448; // Cyrillic_sha + case 0x06dd: return 0x0449; // Cyrillic_shcha + case 0x06df: return 0x044a; // Cyrillic_hardsign + case 0x06d9: return 0x044b; // Cyrillic_yeru + case 0x06d8: return 0x044c; // Cyrillic_softsign + case 0x06dc: return 0x044d; // Cyrillic_e + case 0x06c0: return 0x044e; // Cyrillic_yu + case 0x06d1: return 0x044f; // Cyrillic_ya + case 0x06a3: return 0x0451; // Cyrillic_io + case 0x06a1: return 0x0452; // Serbian_dje + case 0x06a2: return 0x0453; // Macedonia_gje + case 0x06a4: return 0x0454; // Ukrainian_ie + case 0x06a5: return 0x0455; // Macedonia_dse + case 0x06a6: return 0x0456; // Ukrainian_i + case 0x06a7: return 0x0457; // Ukrainian_yi + case 0x06a8: return 0x0458; // Cyrillic_je + case 0x06a9: return 0x0459; // Cyrillic_lje + case 0x06aa: return 0x045a; // Cyrillic_nje + case 0x06ab: return 0x045b; // Serbian_tshe + case 0x06ac: return 0x045c; // Macedonia_kje + case 0x06ae: return 0x045e; // Byelorussian_shortu + case 0x06af: return 0x045f; // Cyrillic_dzhe + case 0x06bd: return 0x0490; // Ukrainian_GHE_WITH_UPTURN + case 0x06ad: return 0x0491; // Ukrainian_ghe_with_upturn + case 0x0680: return 0x0492; // Cyrillic_GHE_bar + case 0x0690: return 0x0493; // Cyrillic_ghe_bar + case 0x0681: return 0x0496; // Cyrillic_ZHE_descender + case 0x0691: return 0x0497; // Cyrillic_zhe_descender + case 0x0682: return 0x049a; // Cyrillic_KA_descender + case 0x0692: return 0x049b; // Cyrillic_ka_descender + case 0x0683: return 0x049c; // Cyrillic_KA_vertstroke + case 0x0693: return 0x049d; // Cyrillic_ka_vertstroke + case 0x0684: return 0x04a2; // Cyrillic_EN_descender + case 0x0694: return 0x04a3; // Cyrillic_en_descender + case 0x0685: return 0x04ae; // Cyrillic_U_straight + case 0x0695: return 0x04af; // Cyrillic_u_straight + case 0x0686: return 0x04b0; // Cyrillic_U_straight_bar + case 0x0696: return 0x04b1; // Cyrillic_u_straight_bar + case 0x0687: return 0x04b2; // Cyrillic_HA_descender + case 0x0697: return 0x04b3; // Cyrillic_ha_descender + case 0x0688: return 0x04b6; // Cyrillic_CHE_descender + case 0x0698: return 0x04b7; // Cyrillic_che_descender + case 0x0689: return 0x04b8; // Cyrillic_CHE_vertstroke + case 0x0699: return 0x04b9; // Cyrillic_che_vertstroke + case 0x068a: return 0x04ba; // Cyrillic_SHHA + case 0x069a: return 0x04bb; // Cyrillic_shha + case 0x068c: return 0x04d8; // Cyrillic_SCHWA + case 0x069c: return 0x04d9; // Cyrillic_schwa + case 0x068d: return 0x04e2; // Cyrillic_I_macron + case 0x069d: return 0x04e3; // Cyrillic_i_macron + case 0x068e: return 0x04e8; // Cyrillic_O_bar + case 0x069e: return 0x04e9; // Cyrillic_o_bar + case 0x068f: return 0x04ee; // Cyrillic_U_macron + case 0x069f: return 0x04ef; // Cyrillic_u_macron + case 0x14b2: return 0x0531; // Armenian_AYB + case 0x14b4: return 0x0532; // Armenian_BEN + case 0x14b6: return 0x0533; // Armenian_GIM + case 0x14b8: return 0x0534; // Armenian_DA + case 0x14ba: return 0x0535; // Armenian_YECH + case 0x14bc: return 0x0536; // Armenian_ZA + case 0x14be: return 0x0537; // Armenian_E + case 0x14c0: return 0x0538; // Armenian_AT + case 0x14c2: return 0x0539; // Armenian_TO + case 0x14c4: return 0x053a; // Armenian_ZHE + case 0x14c6: return 0x053b; // Armenian_INI + case 0x14c8: return 0x053c; // Armenian_LYUN + case 0x14ca: return 0x053d; // Armenian_KHE + case 0x14cc: return 0x053e; // Armenian_TSA + case 0x14ce: return 0x053f; // Armenian_KEN + case 0x14d0: return 0x0540; // Armenian_HO + case 0x14d2: return 0x0541; // Armenian_DZA + case 0x14d4: return 0x0542; // Armenian_GHAT + case 0x14d6: return 0x0543; // Armenian_TCHE + case 0x14d8: return 0x0544; // Armenian_MEN + case 0x14da: return 0x0545; // Armenian_HI + case 0x14dc: return 0x0546; // Armenian_NU + case 0x14de: return 0x0547; // Armenian_SHA + case 0x14e0: return 0x0548; // Armenian_VO + case 0x14e2: return 0x0549; // Armenian_CHA + case 0x14e4: return 0x054a; // Armenian_PE + case 0x14e6: return 0x054b; // Armenian_JE + case 0x14e8: return 0x054c; // Armenian_RA + case 0x14ea: return 0x054d; // Armenian_SE + case 0x14ec: return 0x054e; // Armenian_VEV + case 0x14ee: return 0x054f; // Armenian_TYUN + case 0x14f0: return 0x0550; // Armenian_RE + case 0x14f2: return 0x0551; // Armenian_TSO + case 0x14f4: return 0x0552; // Armenian_VYUN + case 0x14f6: return 0x0553; // Armenian_PYUR + case 0x14f8: return 0x0554; // Armenian_KE + case 0x14fa: return 0x0555; // Armenian_O + case 0x14fc: return 0x0556; // Armenian_FE + case 0x14fe: return 0x055a; // Armenian_apostrophe + case 0x14b0: return 0x055b; // Armenian_shesht + case 0x14af: return 0x055c; // Armenian_amanak + case 0x14aa: return 0x055d; // Armenian_but + case 0x14b1: return 0x055e; // Armenian_paruyk + case 0x14b3: return 0x0561; // Armenian_ayb + case 0x14b5: return 0x0562; // Armenian_ben + case 0x14b7: return 0x0563; // Armenian_gim + case 0x14b9: return 0x0564; // Armenian_da + case 0x14bb: return 0x0565; // Armenian_yech + case 0x14bd: return 0x0566; // Armenian_za + case 0x14bf: return 0x0567; // Armenian_e + case 0x14c1: return 0x0568; // Armenian_at + case 0x14c3: return 0x0569; // Armenian_to + case 0x14c5: return 0x056a; // Armenian_zhe + case 0x14c7: return 0x056b; // Armenian_ini + case 0x14c9: return 0x056c; // Armenian_lyun + case 0x14cb: return 0x056d; // Armenian_khe + case 0x14cd: return 0x056e; // Armenian_tsa + case 0x14cf: return 0x056f; // Armenian_ken + case 0x14d1: return 0x0570; // Armenian_ho + case 0x14d3: return 0x0571; // Armenian_dza + case 0x14d5: return 0x0572; // Armenian_ghat + case 0x14d7: return 0x0573; // Armenian_tche + case 0x14d9: return 0x0574; // Armenian_men + case 0x14db: return 0x0575; // Armenian_hi + case 0x14dd: return 0x0576; // Armenian_nu + case 0x14df: return 0x0577; // Armenian_sha + case 0x14e1: return 0x0578; // Armenian_vo + case 0x14e3: return 0x0579; // Armenian_cha + case 0x14e5: return 0x057a; // Armenian_pe + case 0x14e7: return 0x057b; // Armenian_je + case 0x14e9: return 0x057c; // Armenian_ra + case 0x14eb: return 0x057d; // Armenian_se + case 0x14ed: return 0x057e; // Armenian_vev + case 0x14ef: return 0x057f; // Armenian_tyun + case 0x14f1: return 0x0580; // Armenian_re + case 0x14f3: return 0x0581; // Armenian_tso + case 0x14f5: return 0x0582; // Armenian_vyun + case 0x14f7: return 0x0583; // Armenian_pyur + case 0x14f9: return 0x0584; // Armenian_ke + case 0x14fb: return 0x0585; // Armenian_o + case 0x14fd: return 0x0586; // Armenian_fe + case 0x14a2: return 0x0587; // Armenian_ligature_ew + case 0x14a3: return 0x0589; // Armenian_verjaket + case 0x14ad: return 0x058a; // Armenian_yentamna + case 0x0ce0: return 0x05d0; // hebrew_aleph + case 0x0ce1: return 0x05d1; // hebrew_beth + case 0x0ce2: return 0x05d2; // hebrew_gimmel + case 0x0ce3: return 0x05d3; // hebrew_daleth + case 0x0ce4: return 0x05d4; // hebrew_he + case 0x0ce5: return 0x05d5; // hebrew_waw + case 0x0ce6: return 0x05d6; // hebrew_zayin + case 0x0ce7: return 0x05d7; // hebrew_het + case 0x0ce8: return 0x05d8; // hebrew_teth + case 0x0ce9: return 0x05d9; // hebrew_yod + case 0x0cea: return 0x05da; // hebrew_finalkaph + case 0x0ceb: return 0x05db; // hebrew_kaph + case 0x0cec: return 0x05dc; // hebrew_lamed + case 0x0ced: return 0x05dd; // hebrew_finalmem + case 0x0cee: return 0x05de; // hebrew_mem + case 0x0cef: return 0x05df; // hebrew_finalnun + case 0x0cf0: return 0x05e0; // hebrew_nun + case 0x0cf1: return 0x05e1; // hebrew_samekh + case 0x0cf2: return 0x05e2; // hebrew_ayin + case 0x0cf3: return 0x05e3; // hebrew_finalpe + case 0x0cf4: return 0x05e4; // hebrew_pe + case 0x0cf5: return 0x05e5; // hebrew_finalzadi + case 0x0cf6: return 0x05e6; // hebrew_zadi + case 0x0cf7: return 0x05e7; // hebrew_qoph + case 0x0cf8: return 0x05e8; // hebrew_resh + case 0x0cf9: return 0x05e9; // hebrew_shin + case 0x0cfa: return 0x05ea; // hebrew_taw + case 0x05ac: return 0x060c; // Arabic_comma + case 0x05bb: return 0x061b; // Arabic_semicolon + case 0x05bf: return 0x061f; // Arabic_question_mark + case 0x05c1: return 0x0621; // Arabic_hamza + case 0x05c2: return 0x0622; // Arabic_maddaonalef + case 0x05c3: return 0x0623; // Arabic_hamzaonalef + case 0x05c4: return 0x0624; // Arabic_hamzaonwaw + case 0x05c5: return 0x0625; // Arabic_hamzaunderalef + case 0x05c6: return 0x0626; // Arabic_hamzaonyeh + case 0x05c7: return 0x0627; // Arabic_alef + case 0x05c8: return 0x0628; // Arabic_beh + case 0x05c9: return 0x0629; // Arabic_tehmarbuta + case 0x05ca: return 0x062a; // Arabic_teh + case 0x05cb: return 0x062b; // Arabic_theh + case 0x05cc: return 0x062c; // Arabic_jeem + case 0x05cd: return 0x062d; // Arabic_hah + case 0x05ce: return 0x062e; // Arabic_khah + case 0x05cf: return 0x062f; // Arabic_dal + case 0x05d0: return 0x0630; // Arabic_thal + case 0x05d1: return 0x0631; // Arabic_ra + case 0x05d2: return 0x0632; // Arabic_zain + case 0x05d3: return 0x0633; // Arabic_seen + case 0x05d4: return 0x0634; // Arabic_sheen + case 0x05d5: return 0x0635; // Arabic_sad + case 0x05d6: return 0x0636; // Arabic_dad + case 0x05d7: return 0x0637; // Arabic_tah + case 0x05d8: return 0x0638; // Arabic_zah + case 0x05d9: return 0x0639; // Arabic_ain + case 0x05da: return 0x063a; // Arabic_ghain + case 0x05e0: return 0x0640; // Arabic_tatweel + case 0x05e1: return 0x0641; // Arabic_feh + case 0x05e2: return 0x0642; // Arabic_qaf + case 0x05e3: return 0x0643; // Arabic_kaf + case 0x05e4: return 0x0644; // Arabic_lam + case 0x05e5: return 0x0645; // Arabic_meem + case 0x05e6: return 0x0646; // Arabic_noon + case 0x05e7: return 0x0647; // Arabic_ha + case 0x05e8: return 0x0648; // Arabic_waw + case 0x05e9: return 0x0649; // Arabic_alefmaksura + case 0x05ea: return 0x064a; // Arabic_yeh + case 0x05eb: return 0x064b; // Arabic_fathatan + case 0x05ec: return 0x064c; // Arabic_dammatan + case 0x05ed: return 0x064d; // Arabic_kasratan + case 0x05ee: return 0x064e; // Arabic_fatha + case 0x05ef: return 0x064f; // Arabic_damma + case 0x05f0: return 0x0650; // Arabic_kasra + case 0x05f1: return 0x0651; // Arabic_shadda + case 0x05f2: return 0x0652; // Arabic_sukun + case 0x05f3: return 0x0653; // Arabic_madda_above + case 0x05f4: return 0x0654; // Arabic_hamza_above + case 0x05f5: return 0x0655; // Arabic_hamza_below + case 0x05b0: return 0x0660; // Arabic_0 + case 0x05b1: return 0x0661; // Arabic_1 + case 0x05b2: return 0x0662; // Arabic_2 + case 0x05b3: return 0x0663; // Arabic_3 + case 0x05b4: return 0x0664; // Arabic_4 + case 0x05b5: return 0x0665; // Arabic_5 + case 0x05b6: return 0x0666; // Arabic_6 + case 0x05b7: return 0x0667; // Arabic_7 + case 0x05b8: return 0x0668; // Arabic_8 + case 0x05b9: return 0x0669; // Arabic_9 + case 0x05a5: return 0x066a; // Arabic_percent + case 0x05a6: return 0x0670; // Arabic_superscript_alef + case 0x05a7: return 0x0679; // Arabic_tteh + case 0x05a8: return 0x067e; // Arabic_peh + case 0x05a9: return 0x0686; // Arabic_tcheh + case 0x05aa: return 0x0688; // Arabic_ddal + case 0x05ab: return 0x0691; // Arabic_rreh + case 0x05f6: return 0x0698; // Arabic_jeh + case 0x05f7: return 0x06a4; // Arabic_veh + case 0x05f8: return 0x06a9; // Arabic_keheh + case 0x05f9: return 0x06af; // Arabic_gaf + case 0x05fa: return 0x06ba; // Arabic_noon_ghunna + case 0x05fb: return 0x06be; // Arabic_heh_doachashmee + case 0x05fe: return 0x06c1; // Arabic_heh_goal + case 0x05fc: return 0x06cc; // Farsi_yeh + case 0x05fd: return 0x06d2; // Arabic_yeh_baree + case 0x05ae: return 0x06d4; // Arabic_fullstop + case 0x0590: return 0x06f0; // Farsi_0 + case 0x0591: return 0x06f1; // Farsi_1 + case 0x0592: return 0x06f2; // Farsi_2 + case 0x0593: return 0x06f3; // Farsi_3 + case 0x0594: return 0x06f4; // Farsi_4 + case 0x0595: return 0x06f5; // Farsi_5 + case 0x0596: return 0x06f6; // Farsi_6 + case 0x0597: return 0x06f7; // Farsi_7 + case 0x0598: return 0x06f8; // Farsi_8 + case 0x0599: return 0x06f9; // Farsi_9 + case 0x0da1: return 0x0e01; // Thai_kokai + case 0x0da2: return 0x0e02; // Thai_khokhai + case 0x0da3: return 0x0e03; // Thai_khokhuat + case 0x0da4: return 0x0e04; // Thai_khokhwai + case 0x0da5: return 0x0e05; // Thai_khokhon + case 0x0da6: return 0x0e06; // Thai_khorakhang + case 0x0da7: return 0x0e07; // Thai_ngongu + case 0x0da8: return 0x0e08; // Thai_chochan + case 0x0da9: return 0x0e09; // Thai_choching + case 0x0daa: return 0x0e0a; // Thai_chochang + case 0x0dab: return 0x0e0b; // Thai_soso + case 0x0dac: return 0x0e0c; // Thai_chochoe + case 0x0dad: return 0x0e0d; // Thai_yoying + case 0x0dae: return 0x0e0e; // Thai_dochada + case 0x0daf: return 0x0e0f; // Thai_topatak + case 0x0db0: return 0x0e10; // Thai_thothan + case 0x0db1: return 0x0e11; // Thai_thonangmontho + case 0x0db2: return 0x0e12; // Thai_thophuthao + case 0x0db3: return 0x0e13; // Thai_nonen + case 0x0db4: return 0x0e14; // Thai_dodek + case 0x0db5: return 0x0e15; // Thai_totao + case 0x0db6: return 0x0e16; // Thai_thothung + case 0x0db7: return 0x0e17; // Thai_thothahan + case 0x0db8: return 0x0e18; // Thai_thothong + case 0x0db9: return 0x0e19; // Thai_nonu + case 0x0dba: return 0x0e1a; // Thai_bobaimai + case 0x0dbb: return 0x0e1b; // Thai_popla + case 0x0dbc: return 0x0e1c; // Thai_phophung + case 0x0dbd: return 0x0e1d; // Thai_fofa + case 0x0dbe: return 0x0e1e; // Thai_phophan + case 0x0dbf: return 0x0e1f; // Thai_fofan + case 0x0dc0: return 0x0e20; // Thai_phosamphao + case 0x0dc1: return 0x0e21; // Thai_moma + case 0x0dc2: return 0x0e22; // Thai_yoyak + case 0x0dc3: return 0x0e23; // Thai_rorua + case 0x0dc4: return 0x0e24; // Thai_ru + case 0x0dc5: return 0x0e25; // Thai_loling + case 0x0dc6: return 0x0e26; // Thai_lu + case 0x0dc7: return 0x0e27; // Thai_wowaen + case 0x0dc8: return 0x0e28; // Thai_sosala + case 0x0dc9: return 0x0e29; // Thai_sorusi + case 0x0dca: return 0x0e2a; // Thai_sosua + case 0x0dcb: return 0x0e2b; // Thai_hohip + case 0x0dcc: return 0x0e2c; // Thai_lochula + case 0x0dcd: return 0x0e2d; // Thai_oang + case 0x0dce: return 0x0e2e; // Thai_honokhuk + case 0x0dcf: return 0x0e2f; // Thai_paiyannoi + case 0x0dd0: return 0x0e30; // Thai_saraa + case 0x0dd1: return 0x0e31; // Thai_maihanakat + case 0x0dd2: return 0x0e32; // Thai_saraaa + case 0x0dd3: return 0x0e33; // Thai_saraam + case 0x0dd4: return 0x0e34; // Thai_sarai + case 0x0dd5: return 0x0e35; // Thai_saraii + case 0x0dd6: return 0x0e36; // Thai_saraue + case 0x0dd7: return 0x0e37; // Thai_sarauee + case 0x0dd8: return 0x0e38; // Thai_sarau + case 0x0dd9: return 0x0e39; // Thai_sarauu + case 0x0dda: return 0x0e3a; // Thai_phinthu + case 0x0ddf: return 0x0e3f; // Thai_baht + case 0x0de0: return 0x0e40; // Thai_sarae + case 0x0de1: return 0x0e41; // Thai_saraae + case 0x0de2: return 0x0e42; // Thai_sarao + case 0x0de3: return 0x0e43; // Thai_saraaimaimuan + case 0x0de4: return 0x0e44; // Thai_saraaimaimalai + case 0x0de5: return 0x0e45; // Thai_lakkhangyao + case 0x0de6: return 0x0e46; // Thai_maiyamok + case 0x0de7: return 0x0e47; // Thai_maitaikhu + case 0x0de8: return 0x0e48; // Thai_maiek + case 0x0de9: return 0x0e49; // Thai_maitho + case 0x0dea: return 0x0e4a; // Thai_maitri + case 0x0deb: return 0x0e4b; // Thai_maichattawa + case 0x0dec: return 0x0e4c; // Thai_thanthakhat + case 0x0ded: return 0x0e4d; // Thai_nikhahit + case 0x0df0: return 0x0e50; // Thai_leksun + case 0x0df1: return 0x0e51; // Thai_leknung + case 0x0df2: return 0x0e52; // Thai_leksong + case 0x0df3: return 0x0e53; // Thai_leksam + case 0x0df4: return 0x0e54; // Thai_leksi + case 0x0df5: return 0x0e55; // Thai_lekha + case 0x0df6: return 0x0e56; // Thai_lekhok + case 0x0df7: return 0x0e57; // Thai_lekchet + case 0x0df8: return 0x0e58; // Thai_lekpaet + case 0x0df9: return 0x0e59; // Thai_lekkao + case 0x15d0: return 0x10d0; // Georgian_an + case 0x15d1: return 0x10d1; // Georgian_ban + case 0x15d2: return 0x10d2; // Georgian_gan + case 0x15d3: return 0x10d3; // Georgian_don + case 0x15d4: return 0x10d4; // Georgian_en + case 0x15d5: return 0x10d5; // Georgian_vin + case 0x15d6: return 0x10d6; // Georgian_zen + case 0x15d7: return 0x10d7; // Georgian_tan + case 0x15d8: return 0x10d8; // Georgian_in + case 0x15d9: return 0x10d9; // Georgian_kan + case 0x15da: return 0x10da; // Georgian_las + case 0x15db: return 0x10db; // Georgian_man + case 0x15dc: return 0x10dc; // Georgian_nar + case 0x15dd: return 0x10dd; // Georgian_on + case 0x15de: return 0x10de; // Georgian_par + case 0x15df: return 0x10df; // Georgian_zhar + case 0x15e0: return 0x10e0; // Georgian_rae + case 0x15e1: return 0x10e1; // Georgian_san + case 0x15e2: return 0x10e2; // Georgian_tar + case 0x15e3: return 0x10e3; // Georgian_un + case 0x15e4: return 0x10e4; // Georgian_phar + case 0x15e5: return 0x10e5; // Georgian_khar + case 0x15e6: return 0x10e6; // Georgian_ghan + case 0x15e7: return 0x10e7; // Georgian_qar + case 0x15e8: return 0x10e8; // Georgian_shin + case 0x15e9: return 0x10e9; // Georgian_chin + case 0x15ea: return 0x10ea; // Georgian_can + case 0x15eb: return 0x10eb; // Georgian_jil + case 0x15ec: return 0x10ec; // Georgian_cil + case 0x15ed: return 0x10ed; // Georgian_char + case 0x15ee: return 0x10ee; // Georgian_xan + case 0x15ef: return 0x10ef; // Georgian_jhan + case 0x15f0: return 0x10f0; // Georgian_hae + case 0x15f1: return 0x10f1; // Georgian_he + case 0x15f2: return 0x10f2; // Georgian_hie + case 0x15f3: return 0x10f3; // Georgian_we + case 0x15f4: return 0x10f4; // Georgian_har + case 0x15f5: return 0x10f5; // Georgian_hoe + case 0x15f6: return 0x10f6; // Georgian_fi + case 0x0ed4: return 0x11a8; // Hangul_J_Kiyeog + case 0x0ed5: return 0x11a9; // Hangul_J_SsangKiyeog + case 0x0ed6: return 0x11aa; // Hangul_J_KiyeogSios + case 0x0ed7: return 0x11ab; // Hangul_J_Nieun + case 0x0ed8: return 0x11ac; // Hangul_J_NieunJieuj + case 0x0ed9: return 0x11ad; // Hangul_J_NieunHieuh + case 0x0eda: return 0x11ae; // Hangul_J_Dikeud + case 0x0edb: return 0x11af; // Hangul_J_Rieul + case 0x0edc: return 0x11b0; // Hangul_J_RieulKiyeog + case 0x0edd: return 0x11b1; // Hangul_J_RieulMieum + case 0x0ede: return 0x11b2; // Hangul_J_RieulPieub + case 0x0edf: return 0x11b3; // Hangul_J_RieulSios + case 0x0ee0: return 0x11b4; // Hangul_J_RieulTieut + case 0x0ee1: return 0x11b5; // Hangul_J_RieulPhieuf + case 0x0ee2: return 0x11b6; // Hangul_J_RieulHieuh + case 0x0ee3: return 0x11b7; // Hangul_J_Mieum + case 0x0ee4: return 0x11b8; // Hangul_J_Pieub + case 0x0ee5: return 0x11b9; // Hangul_J_PieubSios + case 0x0ee6: return 0x11ba; // Hangul_J_Sios + case 0x0ee7: return 0x11bb; // Hangul_J_SsangSios + case 0x0ee8: return 0x11bc; // Hangul_J_Ieung + case 0x0ee9: return 0x11bd; // Hangul_J_Jieuj + case 0x0eea: return 0x11be; // Hangul_J_Cieuc + case 0x0eeb: return 0x11bf; // Hangul_J_Khieuq + case 0x0eec: return 0x11c0; // Hangul_J_Tieut + case 0x0eed: return 0x11c1; // Hangul_J_Phieuf + case 0x0eee: return 0x11c2; // Hangul_J_Hieuh + case 0x0ef8: return 0x11eb; // Hangul_J_PanSios + case 0x0ef9: return 0x11f0; // Hangul_J_KkogjiDalrinIeung + case 0x0efa: return 0x11f9; // Hangul_J_YeorinHieuh + case 0x12a1: return 0x1e02; // Babovedot + case 0x12a2: return 0x1e03; // babovedot + case 0x12a6: return 0x1e0a; // Dabovedot + case 0x12ab: return 0x1e0b; // dabovedot + case 0x12b0: return 0x1e1e; // Fabovedot + case 0x12b1: return 0x1e1f; // fabovedot + case 0x16d1: return 0x1e36; // Lbelowdot + case 0x16e1: return 0x1e37; // lbelowdot + case 0x12b4: return 0x1e40; // Mabovedot + case 0x12b5: return 0x1e41; // mabovedot + case 0x12b7: return 0x1e56; // Pabovedot + case 0x12b9: return 0x1e57; // pabovedot + case 0x12bb: return 0x1e60; // Sabovedot + case 0x12bf: return 0x1e61; // sabovedot + case 0x12d7: return 0x1e6a; // Tabovedot + case 0x12f7: return 0x1e6b; // tabovedot + case 0x12a8: return 0x1e80; // Wgrave + case 0x12b8: return 0x1e81; // wgrave + case 0x12aa: return 0x1e82; // Wacute + case 0x12ba: return 0x1e83; // wacute + case 0x12bd: return 0x1e84; // Wdiaeresis + case 0x12be: return 0x1e85; // wdiaeresis + case 0x16a3: return 0x1e8a; // Xabovedot + case 0x16b3: return 0x1e8b; // xabovedot + case 0x1ea0: return 0x1ea0; // Abelowdot + case 0x1ea1: return 0x1ea1; // abelowdot + case 0x1ea2: return 0x1ea2; // Ahook + case 0x1ea3: return 0x1ea3; // ahook + case 0x1ea4: return 0x1ea4; // Acircumflexacute + case 0x1ea5: return 0x1ea5; // acircumflexacute + case 0x1ea6: return 0x1ea6; // Acircumflexgrave + case 0x1ea7: return 0x1ea7; // acircumflexgrave + case 0x1ea8: return 0x1ea8; // Acircumflexhook + case 0x1ea9: return 0x1ea9; // acircumflexhook + case 0x1eaa: return 0x1eaa; // Acircumflextilde + case 0x1eab: return 0x1eab; // acircumflextilde + case 0x1eac: return 0x1eac; // Acircumflexbelowdot + case 0x1ead: return 0x1ead; // acircumflexbelowdot + case 0x1eae: return 0x1eae; // Abreveacute + case 0x1eaf: return 0x1eaf; // abreveacute + case 0x1eb0: return 0x1eb0; // Abrevegrave + case 0x1eb1: return 0x1eb1; // abrevegrave + case 0x1eb2: return 0x1eb2; // Abrevehook + case 0x1eb3: return 0x1eb3; // abrevehook + case 0x1eb4: return 0x1eb4; // Abrevetilde + case 0x1eb5: return 0x1eb5; // abrevetilde + case 0x1eb6: return 0x1eb6; // Abrevebelowdot + case 0x1eb7: return 0x1eb7; // abrevebelowdot + case 0x1eb8: return 0x1eb8; // Ebelowdot + case 0x1eb9: return 0x1eb9; // ebelowdot + case 0x1eba: return 0x1eba; // Ehook + case 0x1ebb: return 0x1ebb; // ehook + case 0x1ebc: return 0x1ebc; // Etilde + case 0x1ebd: return 0x1ebd; // etilde + case 0x1ebe: return 0x1ebe; // Ecircumflexacute + case 0x1ebf: return 0x1ebf; // ecircumflexacute + case 0x1ec0: return 0x1ec0; // Ecircumflexgrave + case 0x1ec1: return 0x1ec1; // ecircumflexgrave + case 0x1ec2: return 0x1ec2; // Ecircumflexhook + case 0x1ec3: return 0x1ec3; // ecircumflexhook + case 0x1ec4: return 0x1ec4; // Ecircumflextilde + case 0x1ec5: return 0x1ec5; // ecircumflextilde + case 0x1ec6: return 0x1ec6; // Ecircumflexbelowdot + case 0x1ec7: return 0x1ec7; // ecircumflexbelowdot + case 0x1ec8: return 0x1ec8; // Ihook + case 0x1ec9: return 0x1ec9; // ihook + case 0x1eca: return 0x1eca; // Ibelowdot + case 0x1ecb: return 0x1ecb; // ibelowdot + case 0x1ecc: return 0x1ecc; // Obelowdot + case 0x1ecd: return 0x1ecd; // obelowdot + case 0x1ece: return 0x1ece; // Ohook + case 0x1ecf: return 0x1ecf; // ohook + case 0x1ed0: return 0x1ed0; // Ocircumflexacute + case 0x1ed1: return 0x1ed1; // ocircumflexacute + case 0x1ed2: return 0x1ed2; // Ocircumflexgrave + case 0x1ed3: return 0x1ed3; // ocircumflexgrave + case 0x1ed4: return 0x1ed4; // Ocircumflexhook + case 0x1ed5: return 0x1ed5; // ocircumflexhook + case 0x1ed6: return 0x1ed6; // Ocircumflextilde + case 0x1ed7: return 0x1ed7; // ocircumflextilde + case 0x1ed8: return 0x1ed8; // Ocircumflexbelowdot + case 0x1ed9: return 0x1ed9; // ocircumflexbelowdot + case 0x1eda: return 0x1eda; // Ohornacute + case 0x1edb: return 0x1edb; // ohornacute + case 0x1edc: return 0x1edc; // Ohorngrave + case 0x1edd: return 0x1edd; // ohorngrave + case 0x1ede: return 0x1ede; // Ohornhook + case 0x1edf: return 0x1edf; // ohornhook + case 0x1ee0: return 0x1ee0; // Ohorntilde + case 0x1ee1: return 0x1ee1; // ohorntilde + case 0x1ee2: return 0x1ee2; // Ohornbelowdot + case 0x1ee3: return 0x1ee3; // ohornbelowdot + case 0x1ee4: return 0x1ee4; // Ubelowdot + case 0x1ee5: return 0x1ee5; // ubelowdot + case 0x1ee6: return 0x1ee6; // Uhook + case 0x1ee7: return 0x1ee7; // uhook + case 0x1ee8: return 0x1ee8; // Uhornacute + case 0x1ee9: return 0x1ee9; // uhornacute + case 0x1eea: return 0x1eea; // Uhorngrave + case 0x1eeb: return 0x1eeb; // uhorngrave + case 0x1eec: return 0x1eec; // Uhornhook + case 0x1eed: return 0x1eed; // uhornhook + case 0x1eee: return 0x1eee; // Uhorntilde + case 0x1eef: return 0x1eef; // uhorntilde + case 0x1ef0: return 0x1ef0; // Uhornbelowdot + case 0x1ef1: return 0x1ef1; // uhornbelowdot + case 0x12ac: return 0x1ef2; // Ygrave + case 0x12bc: return 0x1ef3; // ygrave + case 0x1ef4: return 0x1ef4; // Ybelowdot + case 0x1ef5: return 0x1ef5; // ybelowdot + case 0x1ef6: return 0x1ef6; // Yhook + case 0x1ef7: return 0x1ef7; // yhook + case 0x1ef8: return 0x1ef8; // Ytilde + case 0x1ef9: return 0x1ef9; // ytilde + case 0x0aa2: return 0x2002; // enspace + case 0x0aa1: return 0x2003; // emspace + case 0x0aa3: return 0x2004; // em3space + case 0x0aa4: return 0x2005; // em4space + case 0x0aa5: return 0x2007; // digitspace + case 0x0aa6: return 0x2008; // punctspace + case 0x0aa7: return 0x2009; // thinspace + case 0x0aa8: return 0x200a; // hairspace + case 0x0abb: return 0x2012; // figdash + case 0x14ac: return 0x2013; // Armenian_en_dash + case 0x0aaa: return 0x2013; // endash + case 0x14a8: return 0x2014; // Armenian_em_dash + case 0x0aa9: return 0x2014; // emdash + case 0x07af: return 0x2015; // Greek_horizbar + case 0x0cdf: return 0x2017; // hebrew_doublelowline + case 0x0ad0: return 0x2018; // leftsinglequotemark + case 0x0ad1: return 0x2019; // rightsinglequotemark + case 0x0afd: return 0x201a; // singlelowquotemark + case 0x0ad2: return 0x201c; // leftdoublequotemark + case 0x0ad3: return 0x201d; // rightdoublequotemark + case 0x0afe: return 0x201e; // doublelowquotemark + case 0x0af1: return 0x2020; // dagger + case 0x0af2: return 0x2021; // doubledagger + case 0x0ae6: return 0x2022; // enfilledcircbullet + case 0x0aaf: return 0x2025; // doubbaselinedot + case 0x14ae: return 0x2026; // Armenian_ellipsis + case 0x0aae: return 0x2026; // ellipsis + case 0x0ad6: return 0x2032; // minutes + case 0x0ad7: return 0x2033; // seconds + case 0x0afc: return 0x2038; // caret + case 0x047e: return 0x203e; // overline + case 0x20a0: return 0x20a0; // EcuSign + case 0x20a1: return 0x20a1; // ColonSign + case 0x20a2: return 0x20a2; // CruzeiroSign + case 0x20a3: return 0x20a3; // FFrancSign + case 0x20a4: return 0x20a4; // LiraSign + case 0x20a5: return 0x20a5; // MillSign + case 0x20a6: return 0x20a6; // NairaSign + case 0x20a7: return 0x20a7; // PesetaSign + case 0x20a8: return 0x20a8; // RupeeSign + case 0x0eff: return 0x20a9; // Korean_Won + case 0x20a9: return 0x20a9; // WonSign + case 0x20aa: return 0x20aa; // NewSheqelSign + case 0x20ab: return 0x20ab; // DongSign + case 0x20ac: return 0x20ac; // EuroSign + case 0x0ab8: return 0x2105; // careof + case 0x06b0: return 0x2116; // numerosign + case 0x0afb: return 0x2117; // phonographcopyright + case 0x0ad4: return 0x211e; // prescription + case 0x0ac9: return 0x2122; // trademark + case 0x0ab0: return 0x2153; // onethird + case 0x0ab1: return 0x2154; // twothirds + case 0x0ab2: return 0x2155; // onefifth + case 0x0ab3: return 0x2156; // twofifths + case 0x0ab4: return 0x2157; // threefifths + case 0x0ab5: return 0x2158; // fourfifths + case 0x0ab6: return 0x2159; // onesixth + case 0x0ab7: return 0x215a; // fivesixths + case 0x0ac3: return 0x215b; // oneeighth + case 0x0ac4: return 0x215c; // threeeighths + case 0x0ac5: return 0x215d; // fiveeighths + case 0x0ac6: return 0x215e; // seveneighths + case 0x08fb: return 0x2190; // leftarrow + case 0x08fc: return 0x2191; // uparrow + case 0x08fd: return 0x2192; // rightarrow + case 0x08fe: return 0x2193; // downarrow + case 0x08ce: return 0x21d2; // implies + case 0x08cd: return 0x21d4; // ifonlyif + case 0x08ef: return 0x2202; // partialderivative + case 0x08c5: return 0x2207; // nabla + case 0x0bca: return 0x2218; // jot + case 0x08d6: return 0x221a; // radical + case 0x08c1: return 0x221d; // variation + case 0x08c2: return 0x221e; // infinity + case 0x08de: return 0x2227; // logicaland + case 0x0ba9: return 0x2227; // upcaret + case 0x0ba8: return 0x2228; // downcaret + case 0x08df: return 0x2228; // logicalor + case 0x08dc: return 0x2229; // intersection + case 0x0bc3: return 0x2229; // upshoe + case 0x0bd6: return 0x222a; // downshoe + case 0x08dd: return 0x222a; // union + case 0x08bf: return 0x222b; // integral + case 0x08c0: return 0x2234; // therefore + case 0x08c8: return 0x223c; // approximate + case 0x08c9: return 0x2243; // similarequal + case 0x08bd: return 0x2260; // notequal + case 0x08cf: return 0x2261; // identical + case 0x08bc: return 0x2264; // lessthanequal + case 0x08be: return 0x2265; // greaterthanequal + case 0x08da: return 0x2282; // includedin + case 0x0bda: return 0x2282; // leftshoe + case 0x08db: return 0x2283; // includes + case 0x0bd8: return 0x2283; // rightshoe + case 0x0bdc: return 0x22a2; // lefttack + case 0x0bfc: return 0x22a3; // righttack + case 0x0bce: return 0x22a4; // uptack + case 0x0bc2: return 0x22a5; // downtack + case 0x0bd3: return 0x2308; // upstile + case 0x0bc4: return 0x230a; // downstile + case 0x0afa: return 0x2315; // telephonerecorder + case 0x08a4: return 0x2320; // topintegral + case 0x08a5: return 0x2321; // botintegral + case 0x0bcc: return 0x2395; // quad + case 0x08ab: return 0x239b; // topleftparens + case 0x08ac: return 0x239d; // botleftparens + case 0x08ad: return 0x239e; // toprightparens + case 0x08ae: return 0x23a0; // botrightparens + case 0x08a7: return 0x23a1; // topleftsqbracket + case 0x08a8: return 0x23a3; // botleftsqbracket + case 0x08a9: return 0x23a4; // toprightsqbracket + case 0x08aa: return 0x23a6; // botrightsqbracket + case 0x08af: return 0x23a8; // leftmiddlecurlybrace + case 0x08b0: return 0x23ac; // rightmiddlecurlybrace + case 0x08a1: return 0x23b7; // leftradical + case 0x09ef: return 0x23ba; // horizlinescan1 + case 0x09f0: return 0x23bb; // horizlinescan3 + case 0x09f2: return 0x23bc; // horizlinescan7 + case 0x09f3: return 0x23bd; // horizlinescan9 + case 0x09e2: return 0x2409; // ht + case 0x09e5: return 0x240a; // lf + case 0x09e9: return 0x240b; // vt + case 0x09e3: return 0x240c; // ff + case 0x09e4: return 0x240d; // cr + case 0x0aac: return 0x2423; // signifblank + case 0x09e8: return 0x2424; // nl + case 0x08a3: return 0x2500; // horizconnector + case 0x09f1: return 0x2500; // horizlinescan5 + case 0x09f8: return 0x2502; // vertbar + case 0x08a6: return 0x2502; // vertconnector + case 0x08a2: return 0x250c; // topleftradical + case 0x09ec: return 0x250c; // upleftcorner + case 0x09eb: return 0x2510; // uprightcorner + case 0x09ed: return 0x2514; // lowleftcorner + case 0x09ea: return 0x2518; // lowrightcorner + case 0x09f4: return 0x251c; // leftt + case 0x09f5: return 0x2524; // rightt + case 0x09f7: return 0x252c; // topt + case 0x09f6: return 0x2534; // bott + case 0x09ee: return 0x253c; // crossinglines + case 0x09e1: return 0x2592; // checkerboard + case 0x0ae7: return 0x25aa; // enfilledsqbullet + case 0x0ae1: return 0x25ab; // enopensquarebullet + case 0x0adb: return 0x25ac; // filledrectbullet + case 0x0ae2: return 0x25ad; // openrectbullet + case 0x0adf: return 0x25ae; // emfilledrect + case 0x0acf: return 0x25af; // emopenrectangle + case 0x0ae8: return 0x25b2; // filledtribulletup + case 0x0ae3: return 0x25b3; // opentribulletup + case 0x0add: return 0x25b6; // filledrighttribullet + case 0x0acd: return 0x25b7; // rightopentriangle + case 0x0ae9: return 0x25bc; // filledtribulletdown + case 0x0ae4: return 0x25bd; // opentribulletdown + case 0x0adc: return 0x25c0; // filledlefttribullet + case 0x0acc: return 0x25c1; // leftopentriangle + case 0x09e0: return 0x25c6; // soliddiamond + case 0x0bcf: return 0x25cb; // circle + case 0x0ace: return 0x25cb; // emopencircle + case 0x0ade: return 0x25cf; // emfilledcircle + case 0x0ae0: return 0x25e6; // enopencircbullet + case 0x0ae5: return 0x2606; // openstar + case 0x0af9: return 0x260e; // telephone + case 0x0aca: return 0x2613; // signaturemark + case 0x0aea: return 0x261c; // leftpointer + case 0x0aeb: return 0x261e; // rightpointer + case 0x0af8: return 0x2640; // femalesymbol + case 0x0af7: return 0x2642; // malesymbol + case 0x0aec: return 0x2663; // club + case 0x0aee: return 0x2665; // heart + case 0x0aed: return 0x2666; // diamond + case 0x0af6: return 0x266d; // musicalflat + case 0x0af5: return 0x266f; // musicalsharp + case 0x0af3: return 0x2713; // checkmark + case 0x0af4: return 0x2717; // ballotcross + case 0x0ad9: return 0x271d; // latincross + case 0x0af0: return 0x2720; // maltesecross + case 0x0abc: return 0x27e8; // leftanglebracket + case 0x0abe: return 0x27e9; // rightanglebracket + case 0x04a4: return 0x3001; // kana_comma + case 0x04a1: return 0x3002; // kana_fullstop + case 0x04a2: return 0x300c; // kana_openingbracket + case 0x04a3: return 0x300d; // kana_closingbracket + case 0xfe5e: return 0x3099; // dead_voiced_sound + case 0xfe5f: return 0x309a; // dead_semivoiced_sound + case 0x04de: return 0x309b; // voicedsound + case 0x04df: return 0x309c; // semivoicedsound + case 0x04a7: return 0x30a1; // kana_a + case 0x04b1: return 0x30a2; // kana_A + case 0x04a8: return 0x30a3; // kana_i + case 0x04b2: return 0x30a4; // kana_I + case 0x04a9: return 0x30a5; // kana_u + case 0x04b3: return 0x30a6; // kana_U + case 0x04aa: return 0x30a7; // kana_e + case 0x04b4: return 0x30a8; // kana_E + case 0x04ab: return 0x30a9; // kana_o + case 0x04b5: return 0x30aa; // kana_O + case 0x04b6: return 0x30ab; // kana_KA + case 0x04b7: return 0x30ad; // kana_KI + case 0x04b8: return 0x30af; // kana_KU + case 0x04b9: return 0x30b1; // kana_KE + case 0x04ba: return 0x30b3; // kana_KO + case 0x04bb: return 0x30b5; // kana_SA + case 0x04bc: return 0x30b7; // kana_SHI + case 0x04bd: return 0x30b9; // kana_SU + case 0x04be: return 0x30bb; // kana_SE + case 0x04bf: return 0x30bd; // kana_SO + case 0x04c0: return 0x30bf; // kana_TA + case 0x04c1: return 0x30c1; // kana_CHI + case 0x04af: return 0x30c3; // kana_tsu + case 0x04c2: return 0x30c4; // kana_TSU + case 0x04c3: return 0x30c6; // kana_TE + case 0x04c4: return 0x30c8; // kana_TO + case 0x04c5: return 0x30ca; // kana_NA + case 0x04c6: return 0x30cb; // kana_NI + case 0x04c7: return 0x30cc; // kana_NU + case 0x04c8: return 0x30cd; // kana_NE + case 0x04c9: return 0x30ce; // kana_NO + case 0x04ca: return 0x30cf; // kana_HA + case 0x04cb: return 0x30d2; // kana_HI + case 0x04cc: return 0x30d5; // kana_FU + case 0x04cd: return 0x30d8; // kana_HE + case 0x04ce: return 0x30db; // kana_HO + case 0x04cf: return 0x30de; // kana_MA + case 0x04d0: return 0x30df; // kana_MI + case 0x04d1: return 0x30e0; // kana_MU + case 0x04d2: return 0x30e1; // kana_ME + case 0x04d3: return 0x30e2; // kana_MO + case 0x04ac: return 0x30e3; // kana_ya + case 0x04d4: return 0x30e4; // kana_YA + case 0x04ad: return 0x30e5; // kana_yu + case 0x04d5: return 0x30e6; // kana_YU + case 0x04ae: return 0x30e7; // kana_yo + case 0x04d6: return 0x30e8; // kana_YO + case 0x04d7: return 0x30e9; // kana_RA + case 0x04d8: return 0x30ea; // kana_RI + case 0x04d9: return 0x30eb; // kana_RU + case 0x04da: return 0x30ec; // kana_RE + case 0x04db: return 0x30ed; // kana_RO + case 0x04dc: return 0x30ef; // kana_WA + case 0x04a6: return 0x30f2; // kana_WO + case 0x04dd: return 0x30f3; // kana_N + case 0x04a5: return 0x30fb; // kana_conjunctive + case 0x04b0: return 0x30fc; // prolongedsound + case 0x0ea1: return 0x3131; // Hangul_Kiyeog + case 0x0ea2: return 0x3132; // Hangul_SsangKiyeog + case 0x0ea3: return 0x3133; // Hangul_KiyeogSios + case 0x0ea4: return 0x3134; // Hangul_Nieun + case 0x0ea5: return 0x3135; // Hangul_NieunJieuj + case 0x0ea6: return 0x3136; // Hangul_NieunHieuh + case 0x0ea7: return 0x3137; // Hangul_Dikeud + case 0x0ea8: return 0x3138; // Hangul_SsangDikeud + case 0x0ea9: return 0x3139; // Hangul_Rieul + case 0x0eaa: return 0x313a; // Hangul_RieulKiyeog + case 0x0eab: return 0x313b; // Hangul_RieulMieum + case 0x0eac: return 0x313c; // Hangul_RieulPieub + case 0x0ead: return 0x313d; // Hangul_RieulSios + case 0x0eae: return 0x313e; // Hangul_RieulTieut + case 0x0eaf: return 0x313f; // Hangul_RieulPhieuf + case 0x0eb0: return 0x3140; // Hangul_RieulHieuh + case 0x0eb1: return 0x3141; // Hangul_Mieum + case 0x0eb2: return 0x3142; // Hangul_Pieub + case 0x0eb3: return 0x3143; // Hangul_SsangPieub + case 0x0eb4: return 0x3144; // Hangul_PieubSios + case 0x0eb5: return 0x3145; // Hangul_Sios + case 0x0eb6: return 0x3146; // Hangul_SsangSios + case 0x0eb7: return 0x3147; // Hangul_Ieung + case 0x0eb8: return 0x3148; // Hangul_Jieuj + case 0x0eb9: return 0x3149; // Hangul_SsangJieuj + case 0x0eba: return 0x314a; // Hangul_Cieuc + case 0x0ebb: return 0x314b; // Hangul_Khieuq + case 0x0ebc: return 0x314c; // Hangul_Tieut + case 0x0ebd: return 0x314d; // Hangul_Phieuf + case 0x0ebe: return 0x314e; // Hangul_Hieuh + case 0x0ebf: return 0x314f; // Hangul_A + case 0x0ec0: return 0x3150; // Hangul_AE + case 0x0ec1: return 0x3151; // Hangul_YA + case 0x0ec2: return 0x3152; // Hangul_YAE + case 0x0ec3: return 0x3153; // Hangul_EO + case 0x0ec4: return 0x3154; // Hangul_E + case 0x0ec5: return 0x3155; // Hangul_YEO + case 0x0ec6: return 0x3156; // Hangul_YE + case 0x0ec7: return 0x3157; // Hangul_O + case 0x0ec8: return 0x3158; // Hangul_WA + case 0x0ec9: return 0x3159; // Hangul_WAE + case 0x0eca: return 0x315a; // Hangul_OE + case 0x0ecb: return 0x315b; // Hangul_YO + case 0x0ecc: return 0x315c; // Hangul_U + case 0x0ecd: return 0x315d; // Hangul_WEO + case 0x0ece: return 0x315e; // Hangul_WE + case 0x0ecf: return 0x315f; // Hangul_WI + case 0x0ed0: return 0x3160; // Hangul_YU + case 0x0ed1: return 0x3161; // Hangul_EU + case 0x0ed2: return 0x3162; // Hangul_YI + case 0x0ed3: return 0x3163; // Hangul_I + case 0x0eef: return 0x316d; // Hangul_RieulYeorinHieuh + case 0x0ef0: return 0x3171; // Hangul_SunkyeongeumMieum + case 0x0ef1: return 0x3178; // Hangul_SunkyeongeumPieub + case 0x0ef2: return 0x317f; // Hangul_PanSios + case 0x0ef3: return 0x3181; // Hangul_KkogjiDalrinIeung + case 0x0ef4: return 0x3184; // Hangul_SunkyeongeumPhieuf + case 0x0ef5: return 0x3186; // Hangul_YeorinHieuh + case 0x0ef6: return 0x318d; // Hangul_AraeA + case 0x0ef7: return 0x318e; // Hangul_AraeAE + } + return 0; +} + + +} // namespace priv + +} // namespace sf + +#endif // SFML_KEYSYMTOUNICODEMAPPING_HPP diff --git a/src/SFML/Window/Unix/X11InputManager.cpp b/src/SFML/Window/Unix/KeyboardImpl.cpp similarity index 51% rename from src/SFML/Window/Unix/X11InputManager.cpp rename to src/SFML/Window/Unix/KeyboardImpl.cpp index 8e5517f03..7f70e5883 100644 --- a/src/SFML/Window/Unix/X11InputManager.cpp +++ b/src/SFML/Window/Unix/KeyboardImpl.cpp @@ -25,259 +25,41 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include +#include #include -#include +#include +#include #include +#include +#include #include -namespace sf -{ -namespace priv -{ - namespace { -//////////////////////////////////////////////////////////// -sf::Keyboard::Key keysymToSF(KeySym symbol) -{ - switch (symbol) - { - case XK_Shift_L: return sf::Keyboard::LShift; - case XK_Shift_R: return sf::Keyboard::RShift; - case XK_Control_L: return sf::Keyboard::LControl; - case XK_Control_R: return sf::Keyboard::RControl; - case XK_Alt_L: return sf::Keyboard::LAlt; - case XK_Alt_R: return sf::Keyboard::RAlt; - case XK_Super_L: return sf::Keyboard::LSystem; - case XK_Super_R: return sf::Keyboard::RSystem; - case XK_Menu: return sf::Keyboard::Menu; - case XK_Escape: return sf::Keyboard::Escape; - case XK_semicolon: return sf::Keyboard::SemiColon; - case XK_slash: return sf::Keyboard::Slash; - case XK_equal: return sf::Keyboard::Equal; - case XK_minus: return sf::Keyboard::Dash; - case XK_bracketleft: return sf::Keyboard::LBracket; - case XK_bracketright: return sf::Keyboard::RBracket; - case XK_comma: return sf::Keyboard::Comma; - case XK_period: return sf::Keyboard::Period; - case XK_apostrophe: return sf::Keyboard::Quote; - case XK_backslash: return sf::Keyboard::BackSlash; - case XK_grave: return sf::Keyboard::Tilde; - case XK_space: return sf::Keyboard::Space; - case XK_Return: return sf::Keyboard::Return; - case XK_KP_Enter: return sf::Keyboard::Return; - case XK_BackSpace: return sf::Keyboard::BackSpace; - case XK_Tab: return sf::Keyboard::Tab; - case XK_Prior: return sf::Keyboard::PageUp; - case XK_Next: return sf::Keyboard::PageDown; - case XK_End: return sf::Keyboard::End; - case XK_Home: return sf::Keyboard::Home; - case XK_Insert: return sf::Keyboard::Insert; - case XK_Delete: return sf::Keyboard::Delete; - case XK_KP_Add: return sf::Keyboard::Add; - case XK_KP_Subtract: return sf::Keyboard::Subtract; - case XK_KP_Multiply: return sf::Keyboard::Multiply; - case XK_KP_Divide: return sf::Keyboard::Divide; - case XK_Pause: return sf::Keyboard::Pause; - case XK_F1: return sf::Keyboard::F1; - case XK_F2: return sf::Keyboard::F2; - case XK_F3: return sf::Keyboard::F3; - case XK_F4: return sf::Keyboard::F4; - case XK_F5: return sf::Keyboard::F5; - case XK_F6: return sf::Keyboard::F6; - case XK_F7: return sf::Keyboard::F7; - case XK_F8: return sf::Keyboard::F8; - case XK_F9: return sf::Keyboard::F9; - case XK_F10: return sf::Keyboard::F10; - case XK_F11: return sf::Keyboard::F11; - case XK_F12: return sf::Keyboard::F12; - case XK_F13: return sf::Keyboard::F13; - case XK_F14: return sf::Keyboard::F14; - case XK_F15: return sf::Keyboard::F15; - case XK_Left: return sf::Keyboard::Left; - case XK_Right: return sf::Keyboard::Right; - case XK_Up: return sf::Keyboard::Up; - case XK_Down: return sf::Keyboard::Down; - case XK_KP_Insert: return sf::Keyboard::Numpad0; - case XK_KP_End: return sf::Keyboard::Numpad1; - case XK_KP_Down: return sf::Keyboard::Numpad2; - case XK_KP_Page_Down: return sf::Keyboard::Numpad3; - case XK_KP_Left: return sf::Keyboard::Numpad4; - case XK_KP_Begin: return sf::Keyboard::Numpad5; - case XK_KP_Right: return sf::Keyboard::Numpad6; - case XK_KP_Home: return sf::Keyboard::Numpad7; - case XK_KP_Up: return sf::Keyboard::Numpad8; - case XK_KP_Page_Up: return sf::Keyboard::Numpad9; - case XK_a: return sf::Keyboard::A; - case XK_b: return sf::Keyboard::B; - case XK_c: return sf::Keyboard::C; - case XK_d: return sf::Keyboard::D; - case XK_e: return sf::Keyboard::E; - case XK_f: return sf::Keyboard::F; - case XK_g: return sf::Keyboard::G; - case XK_h: return sf::Keyboard::H; - case XK_i: return sf::Keyboard::I; - case XK_j: return sf::Keyboard::J; - case XK_k: return sf::Keyboard::K; - case XK_l: return sf::Keyboard::L; - case XK_m: return sf::Keyboard::M; - case XK_n: return sf::Keyboard::N; - case XK_o: return sf::Keyboard::O; - case XK_p: return sf::Keyboard::P; - case XK_q: return sf::Keyboard::Q; - case XK_r: return sf::Keyboard::R; - case XK_s: return sf::Keyboard::S; - case XK_t: return sf::Keyboard::T; - case XK_u: return sf::Keyboard::U; - case XK_v: return sf::Keyboard::V; - case XK_w: return sf::Keyboard::W; - case XK_x: return sf::Keyboard::X; - case XK_y: return sf::Keyboard::Y; - case XK_z: return sf::Keyboard::Z; - case XK_0: return sf::Keyboard::Num0; - case XK_1: return sf::Keyboard::Num1; - case XK_2: return sf::Keyboard::Num2; - case XK_3: return sf::Keyboard::Num3; - case XK_4: return sf::Keyboard::Num4; - case XK_5: return sf::Keyboard::Num5; - case XK_6: return sf::Keyboard::Num6; - case XK_7: return sf::Keyboard::Num7; - case XK_8: return sf::Keyboard::Num8; - case XK_9: return sf::Keyboard::Num9; - } - - return sf::Keyboard::Unknown; -} +const KeyCode NullKeyCode = 0; +KeyCode scancodeToKeycode[sf::Keyboard::ScanCodeCount] = { NullKeyCode }; ///< Mapping of SFML scancode to X11 KeyCode +sf::Keyboard::Scancode keycodeToScancode[256] = { sf::Keyboard::ScanUnknown}; ///< Mapping of X11 KeyCode to SFML scancode +bool isMappingInitialized = false; //////////////////////////////////////////////////////////// -KeySym SFtoKeysym(sf::Keyboard::Key key) +bool isValidKeycode(KeyCode keycode) { - // Get the corresponding X11 keysym - KeySym keysym = 0; - switch (key) - { - case sf::Keyboard::LShift: keysym = XK_Shift_L; break; - case sf::Keyboard::RShift: keysym = XK_Shift_R; break; - case sf::Keyboard::LControl: keysym = XK_Control_L; break; - case sf::Keyboard::RControl: keysym = XK_Control_R; break; - case sf::Keyboard::LAlt: keysym = XK_Alt_L; break; - case sf::Keyboard::RAlt: keysym = XK_Alt_R; break; - case sf::Keyboard::LSystem: keysym = XK_Super_L; break; - case sf::Keyboard::RSystem: keysym = XK_Super_R; break; - case sf::Keyboard::Menu: keysym = XK_Menu; break; - case sf::Keyboard::Escape: keysym = XK_Escape; break; - case sf::Keyboard::SemiColon: keysym = XK_semicolon; break; - case sf::Keyboard::Slash: keysym = XK_slash; break; - case sf::Keyboard::Equal: keysym = XK_equal; break; - case sf::Keyboard::Dash: keysym = XK_minus; break; - case sf::Keyboard::LBracket: keysym = XK_bracketleft; break; - case sf::Keyboard::RBracket: keysym = XK_bracketright; break; - case sf::Keyboard::Comma: keysym = XK_comma; break; - case sf::Keyboard::Period: keysym = XK_period; break; - case sf::Keyboard::Quote: keysym = XK_apostrophe; break; - case sf::Keyboard::BackSlash: keysym = XK_backslash; break; - case sf::Keyboard::Tilde: keysym = XK_grave; break; - case sf::Keyboard::Space: keysym = XK_space; break; - case sf::Keyboard::Return: keysym = XK_Return; break; - case sf::Keyboard::BackSpace: keysym = XK_BackSpace; break; - case sf::Keyboard::Tab: keysym = XK_Tab; break; - case sf::Keyboard::PageUp: keysym = XK_Prior; break; - case sf::Keyboard::PageDown: keysym = XK_Next; break; - case sf::Keyboard::End: keysym = XK_End; break; - case sf::Keyboard::Home: keysym = XK_Home; break; - case sf::Keyboard::Insert: keysym = XK_Insert; break; - case sf::Keyboard::Delete: keysym = XK_Delete; break; - case sf::Keyboard::Add: keysym = XK_KP_Add; break; - case sf::Keyboard::Subtract: keysym = XK_KP_Subtract; break; - case sf::Keyboard::Multiply: keysym = XK_KP_Multiply; break; - case sf::Keyboard::Divide: keysym = XK_KP_Divide; break; - case sf::Keyboard::Pause: keysym = XK_Pause; break; - case sf::Keyboard::F1: keysym = XK_F1; break; - case sf::Keyboard::F2: keysym = XK_F2; break; - case sf::Keyboard::F3: keysym = XK_F3; break; - case sf::Keyboard::F4: keysym = XK_F4; break; - case sf::Keyboard::F5: keysym = XK_F5; break; - case sf::Keyboard::F6: keysym = XK_F6; break; - case sf::Keyboard::F7: keysym = XK_F7; break; - case sf::Keyboard::F8: keysym = XK_F8; break; - case sf::Keyboard::F9: keysym = XK_F9; break; - case sf::Keyboard::F10: keysym = XK_F10; break; - case sf::Keyboard::F11: keysym = XK_F11; break; - case sf::Keyboard::F12: keysym = XK_F12; break; - case sf::Keyboard::F13: keysym = XK_F13; break; - case sf::Keyboard::F14: keysym = XK_F14; break; - case sf::Keyboard::F15: keysym = XK_F15; break; - case sf::Keyboard::Left: keysym = XK_Left; break; - case sf::Keyboard::Right: keysym = XK_Right; break; - case sf::Keyboard::Up: keysym = XK_Up; break; - case sf::Keyboard::Down: keysym = XK_Down; break; - case sf::Keyboard::Numpad0: keysym = XK_KP_Insert; break; - case sf::Keyboard::Numpad1: keysym = XK_KP_End; break; - case sf::Keyboard::Numpad2: keysym = XK_KP_Down; break; - case sf::Keyboard::Numpad3: keysym = XK_KP_Page_Down; break; - case sf::Keyboard::Numpad4: keysym = XK_KP_Left; break; - case sf::Keyboard::Numpad5: keysym = XK_KP_Begin; break; - case sf::Keyboard::Numpad6: keysym = XK_KP_Right; break; - case sf::Keyboard::Numpad7: keysym = XK_KP_Home; break; - case sf::Keyboard::Numpad8: keysym = XK_KP_Up; break; - case sf::Keyboard::Numpad9: keysym = XK_KP_Page_Up; break; - case sf::Keyboard::A: keysym = XK_a; break; - case sf::Keyboard::B: keysym = XK_b; break; - case sf::Keyboard::C: keysym = XK_c; break; - case sf::Keyboard::D: keysym = XK_d; break; - case sf::Keyboard::E: keysym = XK_e; break; - case sf::Keyboard::F: keysym = XK_f; break; - case sf::Keyboard::G: keysym = XK_g; break; - case sf::Keyboard::H: keysym = XK_h; break; - case sf::Keyboard::I: keysym = XK_i; break; - case sf::Keyboard::J: keysym = XK_j; break; - case sf::Keyboard::K: keysym = XK_k; break; - case sf::Keyboard::L: keysym = XK_l; break; - case sf::Keyboard::M: keysym = XK_m; break; - case sf::Keyboard::N: keysym = XK_n; break; - case sf::Keyboard::O: keysym = XK_o; break; - case sf::Keyboard::P: keysym = XK_p; break; - case sf::Keyboard::Q: keysym = XK_q; break; - case sf::Keyboard::R: keysym = XK_r; break; - case sf::Keyboard::S: keysym = XK_s; break; - case sf::Keyboard::T: keysym = XK_t; break; - case sf::Keyboard::U: keysym = XK_u; break; - case sf::Keyboard::V: keysym = XK_v; break; - case sf::Keyboard::W: keysym = XK_w; break; - case sf::Keyboard::X: keysym = XK_x; break; - case sf::Keyboard::Y: keysym = XK_y; break; - case sf::Keyboard::Z: keysym = XK_z; break; - case sf::Keyboard::Num0: keysym = XK_0; break; - case sf::Keyboard::Num1: keysym = XK_1; break; - case sf::Keyboard::Num2: keysym = XK_2; break; - case sf::Keyboard::Num3: keysym = XK_3; break; - case sf::Keyboard::Num4: keysym = XK_4; break; - case sf::Keyboard::Num5: keysym = XK_5; break; - case sf::Keyboard::Num6: keysym = XK_6; break; - case sf::Keyboard::Num7: keysym = XK_7; break; - case sf::Keyboard::Num8: keysym = XK_8; break; - case sf::Keyboard::Num9: keysym = XK_9; break; - default: keysym = 0; break; - } - return keysym; + // Valid key code range is [8,255], according to the Xlib manual + return keycode >= 8 || keycode <= 255; } - //////////////////////////////////////////////////////////// sf::Keyboard::Scancode translateKeyCode(Display* display, KeyCode keycode) { - KeySym keySym; - - // Valid key code range is [8,255], according to the Xlib manual - if (keycode < 8 || keycode > 255) + if (!isValidKeycode(keycode)) return sf::Keyboard::ScanUnknown; // Try secondary keysym, for numeric keypad keys // Note: This way we always force "NumLock = ON", which is intentional // since the returned key code should correspond to a physical // location. - keySym = XkbKeycodeToKeysym(display, keycode, 0, 1); + KeySym keySym = XkbKeycodeToKeysym(display, keycode, 0, 1); switch (keySym) { case XK_KP_0: return sf::Keyboard::ScanNumpad0; @@ -442,45 +224,16 @@ sf::Keyboard::Scancode translateKeyCode(Display* display, KeyCode keycode) return sf::Keyboard::ScanUnknown; } - -} // anonymous namespace - - -//////////////////////////////////////////////////////////// -X11InputManager::X11InputManager() : - m_display(NULL) +void initMapping() { - for (int i = 0; i < sf::Keyboard::ScanCodeCount; ++i) - { - m_scancodeToKeycode[i] = 0; - } - - for (int i = 0; i < 256; ++i) - { - m_keycodeToScancode[i] = sf::Keyboard::ScanUnknown; - } -} - - -//////////////////////////////////////////////////////////// -X11InputManager& X11InputManager::getInstance() -{ - static X11InputManager instance; - return instance; -} - - -//////////////////////////////////////////////////////////// -void X11InputManager::initialize(Display* display) -{ - m_display = display; + Display* display = sf::priv::OpenDisplay(); // Find the X11 key code -> SFML key code mapping // This code was inspired by GLFW implementation char name[XkbKeyNameLength + 1]; - XkbDescPtr desc = XkbGetMap(m_display, 0, XkbUseCoreKbd); - XkbGetNames(m_display, XkbKeyNamesMask, desc); + XkbDescPtr desc = XkbGetMap(display, 0, XkbUseCoreKbd); + XkbGetNames(display, XkbKeyNamesMask, desc); sf::Keyboard::Scancode sc; for (int keycode = desc->min_key_code; keycode <= desc->max_key_code; ++keycode) @@ -538,10 +291,10 @@ void X11InputManager::initialize(Display* display) else if (strcmp(name, "AB10") == 0) sc = sf::Keyboard::ScanForwardSlash; else sc = sf::Keyboard::ScanUnknown; - if ((keycode >= 0) && (keycode < 256)) + if (isValidKeycode(keycode)) { - m_scancodeToKeycode[sc] = keycode; - m_keycodeToScancode[keycode] = sc; + scancodeToKeycode[sc] = keycode; + keycodeToScancode[keycode] = sc; } } @@ -549,29 +302,81 @@ void X11InputManager::initialize(Display* display) XkbFreeKeyboard(desc, 0, True); // Translate un-translated keycodes using traditional X11 KeySym lookups - for (int keycode = 0; keycode < 256; ++keycode) + // Valid keycodes are [8;255], so we only initialize them + for (int keycode = 8; keycode < 256; ++keycode) { - if (m_keycodeToScancode[keycode] == sf::Keyboard::ScanUnknown) + if (keycodeToScancode[keycode] == sf::Keyboard::ScanUnknown) { - sf::Keyboard::Scancode sc = translateKeyCode(m_display, keycode); - m_scancodeToKeycode[sc] = keycode; - m_keycodeToScancode[keycode] = sc; + sf::Keyboard::Scancode sc = translateKeyCode(display, keycode); + scancodeToKeycode[sc] = keycode; + keycodeToScancode[keycode] = sc; } } + + sf::priv::CloseDisplay(display); + + isMappingInitialized = true; } - - -namespace { //////////////////////////////////////////////////////////// -bool isKeyPressedImpl(Display* display, KeyCode keycode) +KeyCode SFScancodeToKeyCode(sf::Keyboard::Scancode code) { - if (keycode != 0) + if (!isMappingInitialized) + initMapping(); + + return scancodeToKeycode[code]; +} + +//////////////////////////////////////////////////////////// +sf::Keyboard::Scancode keyCodeToSFScancode(KeyCode code) +{ + if (!isMappingInitialized) + initMapping(); + + if (isValidKeycode(code)) + return keycodeToScancode[code]; + return sf::Keyboard::ScanUnknown; +} + +//////////////////////////////////////////////////////////// +KeyCode SFKeyToKeyCode(sf::Keyboard::Key key) +{ + KeySym keysym = sf::priv::SFKeyToKeySym(key); + if (keysym != NoSymbol) { + Display* display = sf::priv::OpenDisplay(); + KeyCode keycode = XKeysymToKeycode(display, keysym); + sf::priv::CloseDisplay(display); + return keycode; + } + return NullKeyCode; +} + +//////////////////////////////////////////////////////////// +KeySym SFScancodeToKeySym(sf::Keyboard::Scancode code) +{ + Display* display = sf::priv::OpenDisplay(); + KeySym keysym = NoSymbol; + KeyCode keycode = SFScancodeToKeyCode(code); + if (keycode != NullKeyCode) // ensure that this Scancode is mapped to keycode + keysym = XkbKeycodeToKeysym(display, keycode, 0, 0); + sf::priv::CloseDisplay(display); + return keysym; +} + +//////////////////////////////////////////////////////////// +bool isKeyPressedImpl(KeyCode keycode) +{ + if (keycode != NullKeyCode) + { + Display* display = sf::priv::OpenDisplay(); + // Get the whole keyboard state char keys[32]; XQueryKeymap(display, keys); + sf::priv::CloseDisplay(display); + // Check our keycode return (keys[keycode / 8] & (1 << (keycode % 8))) != 0; } @@ -580,57 +385,171 @@ bool isKeyPressedImpl(Display* display, KeyCode keycode) } // anonymous namespace -//////////////////////////////////////////////////////////// -bool X11InputManager::isKeyPressed(sf::Keyboard::Key key) const +namespace sf { - KeyCode keycode = SFtoKeyCode(key); - return isKeyPressedImpl(m_display, keycode); +namespace priv +{ + +//////////////////////////////////////////////////////////// +bool KeyboardImpl::isKeyPressed(Keyboard::Key key) +{ + KeyCode keycode = SFKeyToKeyCode(key); + return isKeyPressedImpl(keycode); } //////////////////////////////////////////////////////////// -bool X11InputManager::isKeyPressed(sf::Keyboard::Scancode code) const +bool KeyboardImpl::isKeyPressed(Keyboard::Scancode code) { - KeyCode keycode = SFtoKeyCode(code); - return isKeyPressedImpl(m_display, keycode); + KeyCode keycode = SFScancodeToKeyCode(code); + return isKeyPressedImpl(keycode); } //////////////////////////////////////////////////////////// -sf::Keyboard::Scancode X11InputManager::unlocalize(sf::Keyboard::Key key) const +Keyboard::Scancode KeyboardImpl::unlocalize(Keyboard::Key key) { - KeyCode keycode = SFtoKeyCode(key); - return keyCodeToSF(keycode); + KeyCode keycode = SFKeyToKeyCode(key); + return keyCodeToSFScancode(keycode); } //////////////////////////////////////////////////////////// -sf::Keyboard::Key X11InputManager::localize(sf::Keyboard::Scancode code) const +Keyboard::Key KeyboardImpl::localize(Keyboard::Scancode code) { - KeyCode keycode = SFtoKeyCode(code); - KeySym keysym = XkbKeycodeToKeysym(m_display, keycode, 0, 0); - return keysymToSF(keysym); + KeySym keysym = SFScancodeToKeySym(code); + return keySymToSFKey(keysym); +} + +//////////////////////////////////////////////////////////// +String KeyboardImpl::getDescription(Keyboard::Scancode code) +{ + bool checkInput = true; + + // these scancodes actually correspond to keys with input + // but we want to return their description, not their behaviour + if (code == Keyboard::ScanEnter || + code == Keyboard::ScanReturn || + code == Keyboard::ScanTab || + code == Keyboard::ScanDelete || + code == Keyboard::ScanBackspace || + code == Keyboard::ScanSpace) + { + checkInput = false; + } + + if (checkInput) + { + KeySym keysym = SFScancodeToKeySym(code); + Uint32 unicode = keysymToUnicode(keysym); + + if (unicode != 0) + return String(unicode); + } + + // Fallback to our best guess for the keys that are known to be independent of the layout. + switch (code) + { + case Keyboard::ScanEnter: return "Enter"; + case Keyboard::ScanEscape: return "Escape"; + case Keyboard::ScanBackspace: return "Backspace"; + case Keyboard::ScanTab: return "Tab"; + case Keyboard::ScanSpace: return "Space"; + + case Keyboard::ScanF1: return "F1"; + case Keyboard::ScanF2: return "F2"; + case Keyboard::ScanF3: return "F3"; + case Keyboard::ScanF4: return "F4"; + case Keyboard::ScanF5: return "F5"; + case Keyboard::ScanF6: return "F6"; + case Keyboard::ScanF7: return "F7"; + case Keyboard::ScanF8: return "F8"; + case Keyboard::ScanF9: return "F9"; + case Keyboard::ScanF10: return "F10"; + case Keyboard::ScanF11: return "F11"; + case Keyboard::ScanF12: return "F12"; + case Keyboard::ScanF13: return "F13"; + case Keyboard::ScanF14: return "F14"; + case Keyboard::ScanF15: return "F15"; + + case Keyboard::ScanCapsLock: return "CapsLock"; + case Keyboard::ScanPrintScreen: return "PrintScreen"; + case Keyboard::ScanScrollLock: return "ScrollLock"; + + case Keyboard::ScanPause: return "Pause"; + case Keyboard::ScanInsert: return "Insert"; + case Keyboard::ScanHome: return "Home"; + case Keyboard::ScanPageUp: return "PageUp"; + case Keyboard::ScanDelete: return "Delete"; + case Keyboard::ScanEnd: return "End"; + case Keyboard::ScanPageDown: return "PageDown"; + + case Keyboard::ScanLeft: return "Left Arrow"; + case Keyboard::ScanRight: return "Right Arrow"; + case Keyboard::ScanDown: return "Down Arrow"; + case Keyboard::ScanUp: return "Up Arrow"; + + case Keyboard::ScanNumLock: return "NumLock"; + case Keyboard::ScanDivide: return "Divide (Numpad)"; + case Keyboard::ScanMultiply: return "Multiply (Numpad)"; + case Keyboard::ScanMinus: return "Minux (Numpad)"; + case Keyboard::ScanPlus: return "Plus (Numpad)"; + case Keyboard::ScanPadEquals: return "Equals (Numpad)"; + case Keyboard::ScanReturn: return "Return (Numpad)"; + case Keyboard::ScanDecimal: return "Decimal (Numpad)"; + + case Keyboard::ScanNumpad0: return "0 (Numpad)"; + case Keyboard::ScanNumpad1: return "1 (Numpad)"; + case Keyboard::ScanNumpad2: return "2 (Numpad)"; + case Keyboard::ScanNumpad3: return "3 (Numpad)"; + case Keyboard::ScanNumpad4: return "4 (Numpad)"; + case Keyboard::ScanNumpad5: return "5 (Numpad)"; + case Keyboard::ScanNumpad6: return "6 (Numpad)"; + case Keyboard::ScanNumpad7: return "7 (Numpad)"; + case Keyboard::ScanNumpad8: return "8 (Numpad)"; + case Keyboard::ScanNumpad9: return "9 (Numpad)"; + + case Keyboard::ScanApplication: return "Application"; + case Keyboard::ScanExecute: return "Execute"; + case Keyboard::ScanHelp: return "Help"; + case Keyboard::ScanMenu: return "Menu"; + case Keyboard::ScanSelect: return "Select"; + case Keyboard::ScanStop: return "Stop"; + case Keyboard::ScanAgain: return "Again"; + case Keyboard::ScanUndo: return "Undo"; + case Keyboard::ScanCut: return "Cut"; + case Keyboard::ScanCopy: return "Copy"; + case Keyboard::ScanPaste: return "Paste"; + case Keyboard::ScanFind: return "Find"; + case Keyboard::ScanMute: return "Mute"; + case Keyboard::ScanVolumeUp: return "Volume Up"; + case Keyboard::ScanVolumeDown: return "Volume Down"; + + case Keyboard::ScanLControl: return "Control (Left)"; + case Keyboard::ScanLShift: return "Shift (Left)"; + case Keyboard::ScanLAlt: return "Alt (Left)"; + case Keyboard::ScanLSystem: return "Meta (Left)"; + case Keyboard::ScanRControl: return "Control (Right)"; + case Keyboard::ScanRShift: return "Shift (Right)"; + case Keyboard::ScanRAlt: return "Alt (Right)"; + case Keyboard::ScanRSystem: return "Meta (Right)"; + } + + return "Unknown Scancode"; // no guess good enough possible. } //////////////////////////////////////////////////////////// -sf::String X11InputManager::getDescription(Keyboard::Scancode code) const +Keyboard::Key KeyboardImpl::getKeyFromEvent(XKeyEvent& event) { - return ""; // TODO -} - - -//////////////////////////////////////////////////////////// -sf::Keyboard::Key X11InputManager::getKeyFromEvent(XKeyEvent& event) const -{ - sf::Keyboard::Key key = Keyboard::Unknown; + Keyboard::Key key = Keyboard::Unknown; // Try each KeySym index (modifier group) until we get a match for (int i = 0; i < 4; ++i) { // Get the SFML keyboard code from the keysym of the key that has been pressed KeySym keysym = XLookupKeysym(&event, i); - key = keysymToSF(keysym); + key = keySymToSFKey(keysym); if (key != Keyboard::Unknown) break; @@ -640,31 +559,9 @@ sf::Keyboard::Key X11InputManager::getKeyFromEvent(XKeyEvent& event) const //////////////////////////////////////////////////////////// -sf::Keyboard::Scancode X11InputManager::getScancodeFromEvent(XKeyEvent& event) const +Keyboard::Scancode KeyboardImpl::getScancodeFromEvent(XKeyEvent& event) { - return keyCodeToSF(event.keycode); -} - - -//////////////////////////////////////////////////////////// -KeyCode X11InputManager::SFtoKeyCode(sf::Keyboard::Key key) const -{ - KeySym keysym = SFtoKeysym(key); - return XKeysymToKeycode(m_display, keysym); -} - - -//////////////////////////////////////////////////////////// -KeyCode X11InputManager::SFtoKeyCode(sf::Keyboard::Scancode code) const -{ - return m_scancodeToKeycode[code]; -} - - -//////////////////////////////////////////////////////////// -sf::Keyboard::Scancode X11InputManager::keyCodeToSF(KeyCode code) const -{ - return m_keycodeToScancode[code]; + return keyCodeToSFScancode(event.keycode); } } // namespace priv diff --git a/src/SFML/Window/Unix/X11InputManager.hpp b/src/SFML/Window/Unix/KeyboardImpl.hpp similarity index 52% rename from src/SFML/Window/Unix/X11InputManager.hpp rename to src/SFML/Window/Unix/KeyboardImpl.hpp index 12948cfec..3b01e217c 100644 --- a/src/SFML/Window/Unix/X11InputManager.hpp +++ b/src/SFML/Window/Unix/KeyboardImpl.hpp @@ -22,8 +22,8 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_X11INPUTMANAGER_HPP -#define SFML_X11INPUTMANAGER_HPP +#ifndef SFML_KEYBOARD_IMPL_HPP +#define SFML_KEYBOARD_IMPL_HPP //////////////////////////////////////////////////////////// // Headers @@ -44,67 +44,39 @@ namespace priv { /// Its purpose is to help sf::priv::InputImpl class. /// //////////////////////////////////////////////////////////// -class X11InputManager +class KeyboardImpl { public: - //////////////////////////////////////////////////////////// - /// \brief Get the unique instance of the class - /// - /// \note Private use only - /// - /// \return Reference to the X11InputManager instance - /// - //////////////////////////////////////////////////////////// - static X11InputManager& getInstance(); - -private: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - X11InputManager(); -public: - - //////////////////////////////////////////////////////////// - /// \brief Initialize the keyboard - /// - /// Builds a mapping between sf::Keyboard::Scancode and - /// X11 keycodes - /// - //////////////////////////////////////////////////////////// - void initialize(Display* display); - //////////////////////////////////////////////////////////// /// \copydoc sf::Keyboard::isKeyPressed(Key) /// //////////////////////////////////////////////////////////// - bool isKeyPressed(sf::Keyboard::Key key) const; + static bool isKeyPressed(Keyboard::Key key); //////////////////////////////////////////////////////////// /// \copydoc sf::Keyboard::isKeyPressed(Scancode) /// //////////////////////////////////////////////////////////// - bool isKeyPressed(sf::Keyboard::Scancode code) const; + static bool isKeyPressed(Keyboard::Scancode code); //////////////////////////////////////////////////////////// /// \copydoc sf::Keyboard::localize /// //////////////////////////////////////////////////////////// - sf::Keyboard::Scancode unlocalize(sf::Keyboard::Key key) const; + static Keyboard::Scancode unlocalize(Keyboard::Key key); //////////////////////////////////////////////////////////// /// \copydoc sf::Keyboard::unlocalize /// //////////////////////////////////////////////////////////// - sf::Keyboard::Key localize(sf::Keyboard::Scancode code) const; + static Keyboard::Key localize(Keyboard::Scancode code); //////////////////////////////////////////////////////////// /// \copydoc sf::Keyboard::getDescription /// //////////////////////////////////////////////////////////// - sf::String getDescription(Keyboard::Scancode code) const; + static String getDescription(Keyboard::Scancode code); //////////////////////////////////////////////////////////// /// \brief Get the sf::Keyboard::Key from XKeyEvent @@ -114,7 +86,7 @@ public: /// \return A key being pressed or released /// //////////////////////////////////////////////////////////// - sf::Keyboard::Key getKeyFromEvent(XKeyEvent& event) const; + static Keyboard::Key getKeyFromEvent(XKeyEvent& event); //////////////////////////////////////////////////////////// /// \brief Get the sf::Keyboard::Scancode from XKeyEvent @@ -124,49 +96,11 @@ public: /// \return A scancode of a key being pressed or released /// //////////////////////////////////////////////////////////// - sf::Keyboard::Scancode getScancodeFromEvent(XKeyEvent& event) const; - -private: - - //////////////////////////////////////////////////////////// - /// \brief Converts sf::Keyboard::Key to X11 keycode - /// - /// \param key A key to be converted - /// - /// \return A corresponding X11 Keycode - /// - //////////////////////////////////////////////////////////// - KeyCode SFtoKeyCode(sf::Keyboard::Key key) const; - - //////////////////////////////////////////////////////////// - /// \brief Converts sf::Keyboard::Scancode to X11 keycode - /// - /// \param code A scancode to be converted - /// - /// \return A corresponding X11 Keycode - /// - //////////////////////////////////////////////////////////// - KeyCode SFtoKeyCode(sf::Keyboard::Scancode code) const; - - //////////////////////////////////////////////////////////// - /// \brief Convert X11 Keycode to sf::Keyboard::Scancode - /// - /// \param code X11 keycode - /// - /// \return The corresponding sf::Keyboard::Scancode - /// - //////////////////////////////////////////////////////////// - sf::Keyboard::Scancode keyCodeToSF(KeyCode code) const; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - KeyCode m_scancodeToKeycode[sf::Keyboard::ScanCodeCount]; ///< Mapping of SFML scancode to X11 KeyCode - sf::Keyboard::Scancode m_keycodeToScancode[256]; ///< Mapping of X11 KeyCode to SFML scancode - Display* m_display; ///< Pointer to the display + static Keyboard::Scancode getScancodeFromEvent(XKeyEvent& event); }; } // namespace priv + } // namespace sf -#endif // SFML_X11INPUTMANAGER_HPP +#endif // SFML_KEYBOARD_IMPL_HPP diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 6c8e1b72a..80422e370 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1688,9 +1689,6 @@ void WindowImplX11::initialize() // Create the hidden cursor createHiddenCursor(); - // init X11 keycode <-> SFML scancode mapping - X11InputManager::getInstance().initialize(m_display); - // Flush the commands queue XFlush(m_display); @@ -1888,27 +1886,16 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) // Key down event case KeyPress: { - Keyboard::Key key = Keyboard::Unknown; - - // Try each KeySym index (modifier group) until we get a match - for (int i = 0; i < 4; ++i) - { - // Get the SFML keyboard code from the keysym of the key that has been pressed - key = keysymToSF(XLookupKeysym(&windowEvent.xkey, i)); - - if (key != Keyboard::Unknown) - break; - } - // Fill the event parameters // TODO: if modifiers are wrong, use XGetModifierMapping to retrieve the actual modifiers mapping Event event; - event.type = Event::KeyPressed; - event.key.code = key; - event.key.alt = windowEvent.xkey.state & Mod1Mask; - event.key.control = windowEvent.xkey.state & ControlMask; - event.key.shift = windowEvent.xkey.state & ShiftMask; - event.key.system = windowEvent.xkey.state & Mod4Mask; + event.type = Event::KeyPressed; + event.key.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); + event.key.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); + event.key.alt = windowEvent.xkey.state & Mod1Mask; + event.key.control = windowEvent.xkey.state & ControlMask; + event.key.shift = windowEvent.xkey.state & ShiftMask; + event.key.system = windowEvent.xkey.state & Mod4Mask; const bool filtered = XFilterEvent(&windowEvent, None); @@ -1995,26 +1982,15 @@ bool WindowImplX11::processEvent(XEvent& windowEvent) // Key up event case KeyRelease: { - Keyboard::Key key = Keyboard::Unknown; - - // Try each KeySym index (modifier group) until we get a match - for (int i = 0; i < 4; ++i) - { - // Get the SFML keyboard code from the keysym of the key that has been released - key = keysymToSF(XLookupKeysym(&windowEvent.xkey, i)); - - if (key != Keyboard::Unknown) - break; - } - // Fill the event parameters Event event; - event.type = Event::KeyReleased; - event.key.code = key; - event.key.alt = windowEvent.xkey.state & Mod1Mask; - event.key.control = windowEvent.xkey.state & ControlMask; - event.key.shift = windowEvent.xkey.state & ShiftMask; - event.key.system = windowEvent.xkey.state & Mod4Mask; + event.type = Event::KeyReleased; + event.key.code = KeyboardImpl::getKeyFromEvent(windowEvent.xkey); + event.key.scancode = KeyboardImpl::getScancodeFromEvent(windowEvent.xkey); + event.key.alt = windowEvent.xkey.state & Mod1Mask; + event.key.control = windowEvent.xkey.state & ControlMask; + event.key.shift = windowEvent.xkey.state & ShiftMask; + event.key.system = windowEvent.xkey.state & Mod4Mask; pushEvent(event); break;