LCOV - code coverage report
Current view: top level - source/ps - KeyName.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 15 62 24.2 %
Date: 2023-01-19 00:18:29 Functions: 5 7 71.4 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : // Ooh, a file of keynames. Fun.
      19             : 
      20             : #include "precompiled.h"
      21             : 
      22             : #include "KeyName.h"
      23             : 
      24             : #include "lib/external_libraries/libsdl.h"
      25             : #include "ps/CStr.h"
      26             : 
      27             : #include <algorithm>
      28             : #include <unordered_map>
      29             : #include <vector>
      30             : 
      31             : // Some scancodes <-> names that SDL doesn't recognise.
      32             : // Those are tested first so they override SDL defaults (useful for UNIFIED keys).
      33         105 : static const std::unordered_map<int, std::vector<CStr>> scancodemap {{
      34             :     { SDL_SCANCODE_DOWN, { "DownArrow" } },
      35             :     { SDL_SCANCODE_UP, { "UpArrow" } },
      36             :     { SDL_SCANCODE_LEFT, { "LeftArrow" } },
      37             :     { SDL_SCANCODE_RIGHT, { "RightArrow" } },
      38             : 
      39             :     { SDL_SCANCODE_EQUALS, { "Plus" } },
      40             :     { SDL_SCANCODE_MINUS, { "Minus" } },
      41             : 
      42             :     { SDL_SCANCODE_KP_ENTER, { "NumEnter" } },
      43             :     { SDL_SCANCODE_KP_DIVIDE, { "NumDivide" } },
      44             :     { SDL_SCANCODE_KP_MULTIPLY, { "NumMultiply" } },
      45             :     { SDL_SCANCODE_KP_EQUALS, { "NumEquals" } },
      46             :     { SDL_SCANCODE_KP_PERIOD, { "NumDecimal" } },
      47             :     { SDL_SCANCODE_KP_PLUS, { "NumPlus" } },
      48             :     { SDL_SCANCODE_KP_MINUS, { "NumMinus" } },
      49             :     { SDL_SCANCODE_KP_0, { "Num0" } },
      50             :     { SDL_SCANCODE_KP_1, { "Num1" } },
      51             :     { SDL_SCANCODE_KP_2, { "Num2" } },
      52             :     { SDL_SCANCODE_KP_3, { "Num3" } },
      53             :     { SDL_SCANCODE_KP_4, { "Num4" } },
      54             :     { SDL_SCANCODE_KP_5, { "Num5" } },
      55             :     { SDL_SCANCODE_KP_6, { "Num6" } },
      56             :     { SDL_SCANCODE_KP_7, { "Num7" } },
      57             :     { SDL_SCANCODE_KP_8, { "Num8" } },
      58             :     { SDL_SCANCODE_KP_9, { "Num9" } },
      59             : 
      60             :     { SDL_SCANCODE_COMMA, { "Comma" } },
      61             :     { SDL_SCANCODE_PERIOD, { "Period" } },
      62             :     { SDL_SCANCODE_APOSTROPHE, { "Quote" } },
      63             :     { SDL_SCANCODE_SEMICOLON, { "Semicolon" } },
      64             :     { SDL_SCANCODE_GRAVE, { "Backquote" } },
      65             :     { SDL_SCANCODE_LEFTBRACKET, { "LeftBracket" } },
      66             :     { SDL_SCANCODE_RIGHTBRACKET, { "RightBracket" } },
      67             :     { SDL_SCANCODE_BACKSLASH, { "Backslash" } },
      68             :     { SDL_SCANCODE_SLASH, { "Slash" } },
      69             : 
      70             :     { SDL_SCANCODE_RETURN, { "Enter" } },
      71             :     { SDL_SCANCODE_ESCAPE, { "Esc" } },
      72             :     { SDL_SCANCODE_PAUSE, { "Break" } },
      73             :     { SDL_SCANCODE_DELETE, { "Del" } },
      74             : 
      75             :     { MOUSE_LEFT, { "MouseLeft" } },
      76             :     { MOUSE_RIGHT, { "MouseRight" } },
      77             :     { MOUSE_MIDDLE, { "MouseMiddle" } },
      78             :     { MOUSE_WHEELUP, { "WheelUp" } },
      79             :     { MOUSE_WHEELDOWN, { "WheelDown" } },
      80             :     { MOUSE_X1, { "WheelLeft", "MouseX1" } },
      81             :     { MOUSE_X2, { "WheelRight", "MouseX2" } },
      82             : 
      83             :     { UNIFIED_SHIFT, { "Shift", "Left Shift", "Right Shift" } },
      84             :     { UNIFIED_CTRL, { "Ctrl", "Left Ctrl", "Right Ctrl" } },
      85             :     { UNIFIED_ALT, { "Alt", "Left Alt", "Right Alt" } },
      86             :     { UNIFIED_SUPER, { "Super", "Left Gui", "Right Gui" } },
      87         104 : }};
      88             : 
      89          25 : SDL_Scancode FindScancode(const CStr8& keyname)
      90             : {
      91             :     // Find (ignoring case) a corresponding scancode, if one exists.
      92             :     std::unordered_map<int, std::vector<CStr>>::const_iterator it =
      93        2350 :         std::find_if(scancodemap.begin(), scancodemap.end(), [&keyname](const std::pair<int, std::vector<CStr>>& names) {
      94        3775 :             return std::find_if(names.second.begin(), names.second.end(), [&keyname](const CStr& t) {
      95        2850 :                 return t.LowerCase() == keyname.LowerCase();
      96        6375 :             })!= names.second.end();
      97        2375 :         });
      98             : 
      99          25 :     if (it != scancodemap.end())
     100           0 :         return static_cast<SDL_Scancode>(it->first);
     101             : 
     102          25 :     SDL_Scancode code = SDL_GetScancodeFromName(keyname.c_str());
     103          25 :     if (code != SDL_SCANCODE_UNKNOWN)
     104          25 :         return code;
     105             : 
     106             :     // Parse SYM_XX codes, see below.
     107           0 :     if (keyname.size() > 4 && keyname.Left(4) == "SYM_")
     108           0 :         return static_cast<SDL_Scancode>(CStr(keyname.substr(4)).ToInt());
     109             : 
     110           0 :     return SDL_SCANCODE_UNKNOWN;
     111             : }
     112             : 
     113           0 : CStr FindScancodeName(SDL_Scancode scancode)
     114             : {
     115           0 :     if (scancodemap.find(scancode) != scancodemap.end())
     116           0 :         return scancodemap.at(scancode).front();
     117             : 
     118           0 :     const char* name = SDL_GetScancodeName(scancode);
     119             :     // Some scancodes have no name, but we must have something to save/load/recognize it, so parse it as SYM_XX
     120           0 :     if (strlen(name) == 0)
     121           0 :         return CStr("SYM_") + CStr::FromInt(scancode);
     122           0 :     return name;
     123             : }
     124             : 
     125             : // Rename some SDL key names (!scancodes) for easier readability.
     126             : // NB: this does not intend to be exhaustive, merely cover the usual suspects.
     127          37 : static const std::unordered_map<SDL_Keycode, CStr> keyNames {{
     128             :     { SDLK_COMMA, "Comma" },
     129             :     { SDLK_SEMICOLON, "Semicolon" },
     130             :     { SDLK_COLON, "Colon" },
     131             :     { SDLK_PERIOD, "Period" },
     132             :     { SDLK_EQUALS, "Equals" },
     133             :     { SDLK_PLUS, "Plus" },
     134             :     { SDLK_MINUS, "Minus" },
     135             : 
     136             :     { SDLK_QUOTE, "SingleQuote" },
     137             :     { SDLK_QUOTEDBL, "DoubleQuote" },
     138             :     { SDLK_BACKQUOTE, "BackQuote" },
     139             : 
     140             :     { SDLK_LEFTPAREN, { "LeftParen" } },
     141             : 
     142             :     { SDLK_LEFTBRACKET, { "LeftBracket" } },
     143             :     { SDLK_RIGHTBRACKET, { "RightBracket" } },
     144             :     { SDLK_BACKSLASH, { "Backslash" } },
     145             :     { SDLK_SLASH, { "Slash" } },
     146             : 
     147             :     { SDLK_KP_ENTER, "NumEnter" },
     148             :     { SDLK_KP_DIVIDE, "NumDivide" },
     149             :     { SDLK_KP_MULTIPLY, "NumMultiply" },
     150             :     { SDLK_KP_EQUALS, "NumEquals" },
     151             :     { SDLK_KP_PERIOD, "NumDecimal" },
     152             :     { SDLK_KP_PLUS, "NumPlus" },
     153             :     { SDLK_KP_MINUS, "NumMinus" },
     154             :     { SDLK_KP_0, "Num0" },
     155             :     { SDLK_KP_1, "Num1" },
     156             :     { SDLK_KP_2, "Num2" },
     157             :     { SDLK_KP_3, "Num3" },
     158             :     { SDLK_KP_4, "Num4" },
     159             :     { SDLK_KP_5, "Num5" },
     160             :     { SDLK_KP_6, "Num6" },
     161             :     { SDLK_KP_7, "Num7" },
     162             :     { SDLK_KP_8, "Num8" },
     163             :     { SDLK_KP_9, "Num9" },
     164             : 
     165             :     { SDLK_UP, "\xe2\x86\x91" },
     166             :     { SDLK_DOWN, "\xe2\x86\x93" },
     167             :     { SDLK_LEFT, "\xe2\x86\x90" },
     168             :     { SDLK_RIGHT, "\xe2\x86\x92" },
     169          36 : }};
     170             : 
     171           0 : CStr FindKeyName(SDL_Scancode scancode)
     172             : {
     173             :     // Mouse and unified modifiers are harcoded.
     174           0 :     if (static_cast<int>(scancode) == UNIFIED_SHIFT)
     175           0 :         return "Shift";
     176           0 :     else if (static_cast<int>(scancode) == UNIFIED_ALT)
     177           0 :         return "Alt";
     178           0 :     else if (static_cast<int>(scancode) == UNIFIED_CTRL)
     179           0 :         return "Ctrl";
     180           0 :     else if (static_cast<int>(scancode) == UNIFIED_SUPER)
     181           0 :         return "Super";
     182           0 :     else if (static_cast<int>(scancode) == MOUSE_LEFT)
     183           0 :         return "MouseLeft";
     184           0 :     else if (static_cast<int>(scancode) == MOUSE_RIGHT)
     185           0 :         return "MouseRight";
     186           0 :     else if (static_cast<int>(scancode) == MOUSE_MIDDLE)
     187           0 :         return "MouseMiddle";
     188           0 :     else if (static_cast<int>(scancode) == MOUSE_WHEELUP)
     189           0 :         return "WheelUp";
     190           0 :     else if (static_cast<int>(scancode) == MOUSE_WHEELDOWN)
     191           0 :         return "WheelDown";
     192           0 :     else if (static_cast<int>(scancode) == MOUSE_X1)
     193           0 :         return "WheelLeft";
     194           0 :     else if (static_cast<int>(scancode) == MOUSE_X2)
     195           0 :         return "WheelRight";
     196             : 
     197           0 :     SDL_Keycode code = SDL_GetKeyFromScancode(scancode);
     198             : 
     199           0 :     if (keyNames.find(code) != keyNames.end())
     200           0 :         return keyNames.at(code);
     201             : 
     202           0 :     if (code != SDLK_UNKNOWN)
     203             :     {
     204           0 :         const char* keyName = SDL_GetKeyName(code);
     205           0 :         if (strlen(keyName) != 0)
     206           0 :             return keyName;
     207             :     }
     208             : 
     209             :     // Try the scancode name.
     210           0 :     const char* name = SDL_GetScancodeName(scancode);
     211             : 
     212             :     // xxtreme hack: some SDLKeycodes map to chars, and we need to escape [ and \ .
     213           0 :     if (keyNames.find(static_cast<SDL_Keycode>(*name)) != keyNames.end())
     214           0 :         return keyNames.at(static_cast<SDL_Keycode>(*name));
     215             : 
     216           0 :     if (strlen(name) != 0)
     217           0 :         return name;
     218             : 
     219             :     // Else, show something regardless, so the player knows it's at least recognized.
     220           0 :     return CStr("SYM_") + CStr::FromInt(scancode);
     221           3 : }
     222             : 
     223             : 

Generated by: LCOV version 1.13