text: // gum
  // Copyright (C) 2014 Rapptz
  
  // 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 GUM_INPUT_KEYBOARD_HPP
  #define GUM_INPUT_KEYBOARD_HPP
  
  #include <gum/core/config.hpp>
  #include <string>
  
  // SDL's keyboard input is fine, just like the event system.
  // Just wrap them up and provide some consistent renames.
  namespace sdl {
  namespace key {
  enum : int32_t {
      unknown           = SDLK_UNKNOWN,
      enter             = SDLK_RETURN,
      escape            = SDLK_ESCAPE,
      backspace         = SDLK_BACKSPACE,
      tab               = SDLK_TAB,
      space             = SDLK_SPACE,
      exclaim           = SDLK_EXCLAIM,
      quotedbl          = SDLK_QUOTEDBL,
      hash              = SDLK_HASH,
      percent           = SDLK_PERCENT,
      dollar            = SDLK_DOLLAR,
      ampersand         = SDLK_AMPERSAND,
      quote             = SDLK_QUOTE,
      leftparen         = SDLK_LEFTPAREN,
      rightparen        = SDLK_RIGHTPAREN,
      asterisk          = SDLK_ASTERISK,
      plus              = SDLK_PLUS,
      comma             = SDLK_COMMA,
      minus             = SDLK_MINUS,
      period            = SDLK_PERIOD,
      slash             = SDLK_SLASH,
      zero              = SDLK_0,
      one               = SDLK_1,
      two               = SDLK_2,
      three             = SDLK_3,
      four              = SDLK_4,
      five              = SDLK_5,
      six               = SDLK_6,
      seven             = SDLK_7,
      eight             = SDLK_8,
      nine              = SDLK_9,
      colon             = SDLK_COLON,
      semicolon         = SDLK_SEMICOLON,
      less              = SDLK_LESS,
      equals            = SDLK_EQUALS,
      greater           = SDLK_GREATER,
      question          = SDLK_QUESTION,
      at                = SDLK_AT,
      leftbracket       = SDLK_LEFTBRACKET,
      backslash         = SDLK_BACKSLASH,
      rightbracket      = SDLK_RIGHTBRACKET,
      caret             = SDLK_CARET,
      underscore        = SDLK_UNDERSCORE,
      backquote         = SDLK_BACKQUOTE,
      a                 = SDLK_a,
      b                 = SDLK_b,
      c                 = SDLK_c,
      d                 = SDLK_d,
      e                 = SDLK_e,
      f                 = SDLK_f,
      g                 = SDLK_g,
      h                 = SDLK_h,
      i                 = SDLK_i,
      j                 = SDLK_j,
      k                 = SDLK_k,
      l                 = SDLK_l,
      m                 = SDLK_m,
      n                 = SDLK_n,
      o                 = SDLK_o,
      p                 = SDLK_p,
      q                 = SDLK_q,
      r                 = SDLK_r,
      s                 = SDLK_s,
      t                 = SDLK_t,
      u                 = SDLK_u,
      v                 = SDLK_v,
      w                 = SDLK_w,
      x                 = SDLK_x,
      y                 = SDLK_y,
      z                 = SDLK_z,
      capslock          = SDLK_CAPSLOCK,
      f1                = SDLK_F1,
      f2                = SDLK_F2,
      f3                = SDLK_F3,
      f4                = SDLK_F4,
      f5                = SDLK_F5,
      f6                = SDLK_F6,
      f7                = SDLK_F7,
      f8                = SDLK_F8,
      f9                = SDLK_F9,
      f10               = SDLK_F10,
      f11               = SDLK_F11,
      f12               = SDLK_F12,
      printscreen       = SDLK_PRINTSCREEN,
      scrolllock        = SDLK_SCROLLLOCK,
      pause             = SDLK_PAUSE,
      insert            = SDLK_INSERT,
      home              = SDLK_HOME,
      pageup            = SDLK_PAGEUP,
      del               = SDLK_DELETE,
      end               = SDLK_END,
      pagedown          = SDLK_PAGEDOWN,
      right             = SDLK_RIGHT,
      left              = SDLK_LEFT,
      down              = SDLK_DOWN,
      up                = SDLK_UP,
      numlockclear      = SDLK_NUMLOCKCLEAR,
      kp_divide         = SDLK_KP_DIVIDE,
      kp_multiply       = SDLK_KP_MULTIPLY,
      kp_minus          = SDLK_KP_MINUS,
      kp_plus           = SDLK_KP_PLUS,
      kp_enter          = SDLK_KP_ENTER,
      kp_one            = SDLK_KP_1,
      kp_two            = SDLK_KP_2,
      kp_three          = SDLK_KP_3,
      kp_four           = SDLK_KP_4,
      kp_five           = SDLK_KP_5,
      kp_six            = SDLK_KP_6,
      kp_seven          = SDLK_KP_7,
      kp_eight          = SDLK_KP_8,
      kp_nine           = SDLK_KP_9,
      kp_zero           = SDLK_KP_0,
      kp_period         = SDLK_KP_PERIOD,
      application       = SDLK_APPLICATION,
      power             = SDLK_POWER,
      kp_equals         = SDLK_KP_EQUALS,
      f13               = SDLK_F13,
      f14               = SDLK_F14,
      f15               = SDLK_F15,
      f16               = SDLK_F16,
      f17               = SDLK_F17,
      f18               = SDLK_F18,
      f19               = SDLK_F19,
      f20               = SDLK_F20,
      f21               = SDLK_F21,
      f22               = SDLK_F22,
      f23               = SDLK_F23,
      f24               = SDLK_F24,
      execute           = SDLK_EXECUTE,
      help              = SDLK_HELP,
      menu              = SDLK_MENU,
      select            = SDLK_SELECT,
      stop              = SDLK_STOP,
      again             = SDLK_AGAIN,
      undo              = SDLK_UNDO,
      cut               = SDLK_CUT,
      copy              = SDLK_COPY,
      paste             = SDLK_PASTE,
      find              = SDLK_FIND,
      mute              = SDLK_MUTE,
      volumeup          = SDLK_VOLUMEUP,
      volumedown        = SDLK_VOLUMEDOWN,
      kp_comma          = SDLK_KP_COMMA,
      kp_equalsas400    = SDLK_KP_EQUALSAS400,
      alterase          = SDLK_ALTERASE,
      sysreq            = SDLK_SYSREQ,
      cancel            = SDLK_CANCEL,
      clear             = SDLK_CLEAR,
      prior             = SDLK_PRIOR,
      return2           = SDLK_RETURN2,
      separator         = SDLK_SEPARATOR,
      out               = SDLK_OUT,
      oper              = SDLK_OPER,
      clearagain        = SDLK_CLEARAGAIN,
      crsel             = SDLK_CRSEL,
      exsel             = SDLK_EXSEL,
      kp_00             = SDLK_KP_00,
      kp_000            = SDLK_KP_000,
      thousandsseparator= SDLK_THOUSANDSSEPARATOR,
      decimalseparator  = SDLK_DECIMALSEPARATOR,
      currencyunit      = SDLK_CURRENCYUNIT,
      currencysubunit   = SDLK_CURRENCYSUBUNIT,
      kp_leftparen      = SDLK_KP_LEFTPAREN,
      kp_rightparen     = SDLK_KP_RIGHTPAREN,
      kp_leftbrace      = SDLK_KP_LEFTBRACE,
      kp_rightbrace     = SDLK_KP_RIGHTBRACE,
      kp_tab            = SDLK_KP_TAB,
      kp_backspace      = SDLK_KP_BACKSPACE,
      kp_a              = SDLK_KP_A,
      kp_b              = SDLK_KP_B,
      kp_c              = SDLK_KP_C,
      kp_d              = SDLK_KP_D,
      kp_e              = SDLK_KP_E,
      kp_f              = SDLK_KP_F,
      kp_xor            = SDLK_KP_XOR,
      kp_power          = SDLK_KP_POWER,
      kp_percent        = SDLK_KP_PERCENT,
      kp_less           = SDLK_KP_LESS,
      kp_greater        = SDLK_KP_GREATER,
      kp_ampersand      = SDLK_KP_AMPERSAND,
      kp_dblampersand   = SDLK_KP_DBLAMPERSAND,
      kp_verticalbar    = SDLK_KP_VERTICALBAR,
      kp_dblverticalbar = SDLK_KP_DBLVERTICALBAR,
      kp_colon          = SDLK_KP_COLON,
      kp_hash           = SDLK_KP_HASH,
      kp_space          = SDLK_KP_SPACE,
      kp_at             = SDLK_KP_AT,
      kp_exclam         = SDLK_KP_EXCLAM,
      kp_memstore       = SDLK_KP_MEMSTORE,
      kp_memrecall      = SDLK_KP_MEMRECALL,
      kp_memclear       = SDLK_KP_MEMCLEAR,
      kp_memadd         = SDLK_KP_MEMADD,
      kp_memsubtract    = SDLK_KP_MEMSUBTRACT,
      kp_memmultiply    = SDLK_KP_MEMMULTIPLY,
      kp_memdivide      = SDLK_KP_MEMDIVIDE,
      kp_plusminus      = SDLK_KP_PLUSMINUS,
      kp_clear          = SDLK_KP_CLEAR,
      kp_clearentry     = SDLK_KP_CLEARENTRY,
      kp_binary         = SDLK_KP_BINARY,
      kp_octal          = SDLK_KP_OCTAL,
      kp_decimal        = SDLK_KP_DECIMAL,
      kp_hexadecimal    = SDLK_KP_HEXADECIMAL,
      lctrl             = SDLK_LCTRL,
      lshift            = SDLK_LSHIFT,
      lalt              = SDLK_LALT,
      lgui              = SDLK_LGUI,
      rctrl             = SDLK_RCTRL,
      rshift            = SDLK_RSHIFT,
      ralt              = SDLK_RALT,
      rgui              = SDLK_RGUI,
      mode              = SDLK_MODE,
      audionext         = SDLK_AUDIONEXT,
      audioprev         = SDLK_AUDIOPREV,
      audiostop         = SDLK_AUDIOSTOP,
      audioplay         = SDLK_AUDIOPLAY,
      audiomute         = SDLK_AUDIOMUTE,
      mediaselect       = SDLK_MEDIASELECT,
      www               = SDLK_WWW,
      mail              = SDLK_MAIL,
      calculator        = SDLK_CALCULATOR,
      computer          = SDLK_COMPUTER,
      ac_search         = SDLK_AC_SEARCH,
      ac_home           = SDLK_AC_HOME,
      ac_back           = SDLK_AC_BACK,
      ac_forward        = SDLK_AC_FORWARD,
      ac_stop           = SDLK_AC_STOP,
      ac_refresh        = SDLK_AC_REFRESH,
      ac_bookmarks      = SDLK_AC_BOOKMARKS,
      brightnessdown    = SDLK_BRIGHTNESSDOWN,
      brightnessup      = SDLK_BRIGHTNESSUP,
      displayswitch     = SDLK_DISPLAYSWITCH,
      kbdillumtoggle    = SDLK_KBDILLUMTOGGLE,
      kbdillumdown      = SDLK_KBDILLUMDOWN,
      kbdillumup        = SDLK_KBDILLUMUP,
      eject             = SDLK_EJECT,
      sleep             = SDLK_SLEEP
  };
  
  inline int32_t from_string(const std::string& str) noexcept {
      return SDL_GetKeyFromName(str.c_str());
  }
  
  inline int32_t from_scan(int32_t scan_code) noexcept {
      return SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(scan_code));
  }
  
  inline std::string to_string(int32_t key_code) noexcept {
      return SDL_GetKeyName(key_code);
  }
  
  inline bool is_pressed(int32_t key_code) noexcept {
      const auto* data = SDL_GetKeyboardState(nullptr);
      return data[SDL_GetScancodeFromKey(key_code)] != 0;
  }
  } // key
  
  namespace modifier {
  enum : int32_t {
      none     = KMOD_NONE,
      lshift   = KMOD_LSHIFT,
      rshift   = KMOD_RSHIFT,
      lctrl    = KMOD_LCTRL,
      rctrl    = KMOD_RCTRL,
      lalt     = KMOD_LALT,
      ralt     = KMOD_RALT,
      lgui     = KMOD_LGUI,
      rgui     = KMOD_RGUI,
      num      = KMOD_NUM,
      caps     = KMOD_CAPS,
      mode     = KMOD_MODE,
      reserved = KMOD_RESERVED
  };
  
  inline bool is_pressed(int32_t mod_key) noexcept {
      return (SDL_GetModState() & mod_key) == mod_key;
  }
  } // modifier
  
  namespace scan {
  enum : int32_t {
      unknown           = SDL_SCANCODE_UNKNOWN,
      a                 = SDL_SCANCODE_A,
      b                 = SDL_SCANCODE_B,
      c                 = SDL_SCANCODE_C,
      d                 = SDL_SCANCODE_D,
      e                 = SDL_SCANCODE_E,
      f                 = SDL_SCANCODE_F,
      g                 = SDL_SCANCODE_G,
      h                 = SDL_SCANCODE_H,
      i                 = SDL_SCANCODE_I,
      j                 = SDL_SCANCODE_J,
      k                 = SDL_SCANCODE_K,
      l                 = SDL_SCANCODE_L,
      m                 = SDL_SCANCODE_M,
      n                 = SDL_SCANCODE_N,
      o                 = SDL_SCANCODE_O,
      p                 = SDL_SCANCODE_P,
      q                 = SDL_SCANCODE_Q,
      r                 = SDL_SCANCODE_R,
      s                 = SDL_SCANCODE_S,
      t                 = SDL_SCANCODE_T,
      u                 = SDL_SCANCODE_U,
      v                 = SDL_SCANCODE_V,
      w                 = SDL_SCANCODE_W,
      x                 = SDL_SCANCODE_X,
      y                 = SDL_SCANCODE_Y,
      z                 = SDL_SCANCODE_Z,
      one               = SDL_SCANCODE_1,
      two               = SDL_SCANCODE_2,
      three             = SDL_SCANCODE_3,
      four              = SDL_SCANCODE_4,
      five              = SDL_SCANCODE_5,
      six               = SDL_SCANCODE_6,
      seven             = SDL_SCANCODE_7,
      eight             = SDL_SCANCODE_8,
      nine              = SDL_SCANCODE_9,
      zero              = SDL_SCANCODE_0,
      enter             = SDL_SCANCODE_RETURN,
      escape            = SDL_SCANCODE_ESCAPE,
      backspace         = SDL_SCANCODE_BACKSPACE,
      tab               = SDL_SCANCODE_TAB,
      space             = SDL_SCANCODE_SPACE,
      minus             = SDL_SCANCODE_MINUS,
      equals            = SDL_SCANCODE_EQUALS,
      leftbracket       = SDL_SCANCODE_LEFTBRACKET,
      rightbracket      = SDL_SCANCODE_RIGHTBRACKET,
      backslash         = SDL_SCANCODE_BACKSLASH,
      nonushash         = SDL_SCANCODE_NONUSHASH,
      semicolon         = SDL_SCANCODE_SEMICOLON,
      apostrophe        = SDL_SCANCODE_APOSTROPHE,
      grave             = SDL_SCANCODE_GRAVE,
      comma             = SDL_SCANCODE_COMMA,
      period            = SDL_SCANCODE_PERIOD,
      slash             = SDL_SCANCODE_SLASH,
      capslock          = SDL_SCANCODE_CAPSLOCK,
      f1                = SDL_SCANCODE_F1,
      f2                = SDL_SCANCODE_F2,
      f3                = SDL_SCANCODE_F3,
      f4                = SDL_SCANCODE_F4,
      f5                = SDL_SCANCODE_F5,
      f6                = SDL_SCANCODE_F6,
      f7                = SDL_SCANCODE_F7,
      f8                = SDL_SCANCODE_F8,
      f9                = SDL_SCANCODE_F9,
      f10               = SDL_SCANCODE_F10,
      f11               = SDL_SCANCODE_F11,
      f12               = SDL_SCANCODE_F12,
      printscreen       = SDL_SCANCODE_PRINTSCREEN,
      scrolllock        = SDL_SCANCODE_SCROLLLOCK,
      pause             = SDL_SCANCODE_PAUSE,
      insert            = SDL_SCANCODE_INSERT,
      home              = SDL_SCANCODE_HOME,
      pageup            = SDL_SCANCODE_PAGEUP,
      del               = SDL_SCANCODE_DELETE,
      end               = SDL_SCANCODE_END,
      pagedown          = SDL_SCANCODE_PAGEDOWN,
      right             = SDL_SCANCODE_RIGHT,
      left              = SDL_SCANCODE_LEFT,
      down              = SDL_SCANCODE_DOWN,
      up                = SDL_SCANCODE_UP,
      numlockclear      = SDL_SCANCODE_NUMLOCKCLEAR,
      kp_divide         = SDL_SCANCODE_KP_DIVIDE,
      kp_multiply       = SDL_SCANCODE_KP_MULTIPLY,
      kp_minus          = SDL_SCANCODE_KP_MINUS,
      kp_plus           = SDL_SCANCODE_KP_PLUS,
      kp_enter          = SDL_SCANCODE_KP_ENTER,
      kp_1              = SDL_SCANCODE_KP_1,
      kp_2              = SDL_SCANCODE_KP_2,
      kp_3              = SDL_SCANCODE_KP_3,
      kp_4              = SDL_SCANCODE_KP_4,
      kp_5              = SDL_SCANCODE_KP_5,
      kp_6              = SDL_SCANCODE_KP_6,
      kp_7              = SDL_SCANCODE_KP_7,
      kp_8              = SDL_SCANCODE_KP_8,
      kp_9              = SDL_SCANCODE_KP_9,
      kp_0              = SDL_SCANCODE_KP_0,
      kp_period         = SDL_SCANCODE_KP_PERIOD,
      nonusbackslash    = SDL_SCANCODE_NONUSBACKSLASH,
      application       = SDL_SCANCODE_APPLICATION,
      power             = SDL_SCANCODE_POWER,
      kp_equals         = SDL_SCANCODE_KP_EQUALS,
      f13               = SDL_SCANCODE_F13,
      f14               = SDL_SCANCODE_F14,
      f15               = SDL_SCANCODE_F15,
      f16               = SDL_SCANCODE_F16,
      f17               = SDL_SCANCODE_F17,
      f18               = SDL_SCANCODE_F18,
      f19               = SDL_SCANCODE_F19,
      f20               = SDL_SCANCODE_F20,
      f21               = SDL_SCANCODE_F21,
      f22               = SDL_SCANCODE_F22,
      f23               = SDL_SCANCODE_F23,
      f24               = SDL_SCANCODE_F24,
      execute           = SDL_SCANCODE_EXECUTE,
      help              = SDL_SCANCODE_HELP,
      menu              = SDL_SCANCODE_MENU,
      select            = SDL_SCANCODE_SELECT,
      stop              = SDL_SCANCODE_STOP,
      again             = SDL_SCANCODE_AGAIN,
      undo              = SDL_SCANCODE_UNDO,
      cut               = SDL_SCANCODE_CUT,
      copy              = SDL_SCANCODE_COPY,
      paste             = SDL_SCANCODE_PASTE,
      find              = SDL_SCANCODE_FIND,
      mute              = SDL_SCANCODE_MUTE,
      volumeup          = SDL_SCANCODE_VOLUMEUP,
      volumedown        = SDL_SCANCODE_VOLUMEDOWN,
      kp_comma          = SDL_SCANCODE_KP_COMMA,
      kp_equalsas400    = SDL_SCANCODE_KP_EQUALSAS400,
      international1    = SDL_SCANCODE_INTERNATIONAL1,
      international2    = SDL_SCANCODE_INTERNATIONAL2,
      international3    = SDL_SCANCODE_INTERNATIONAL3,
      international4    = SDL_SCANCODE_INTERNATIONAL4,
      international5    = SDL_SCANCODE_INTERNATIONAL5,
      international6    = SDL_SCANCODE_INTERNATIONAL6,
      international7    = SDL_SCANCODE_INTERNATIONAL7,
      international8    = SDL_SCANCODE_INTERNATIONAL8,
      international9    = SDL_SCANCODE_INTERNATIONAL9,
      lang1             = SDL_SCANCODE_LANG1,
      lang2             = SDL_SCANCODE_LANG2,
      lang3             = SDL_SCANCODE_LANG3,
      lang4             = SDL_SCANCODE_LANG4,
      lang5             = SDL_SCANCODE_LANG5,
      lang6             = SDL_SCANCODE_LANG6,
      lang7             = SDL_SCANCODE_LANG7,
      lang8             = SDL_SCANCODE_LANG8,
      lang9             = SDL_SCANCODE_LANG9,
      alterase          = SDL_SCANCODE_ALTERASE,
      sysreq            = SDL_SCANCODE_SYSREQ,
      cancel            = SDL_SCANCODE_CANCEL,
      clear             = SDL_SCANCODE_CLEAR,
      prior             = SDL_SCANCODE_PRIOR,
      return2           = SDL_SCANCODE_RETURN2,
      separator         = SDL_SCANCODE_SEPARATOR,
      out               = SDL_SCANCODE_OUT,
      oper              = SDL_SCANCODE_OPER,
      clearagain        = SDL_SCANCODE_CLEARAGAIN,
      crsel             = SDL_SCANCODE_CRSEL,
      exsel             = SDL_SCANCODE_EXSEL,
      kp_00             = SDL_SCANCODE_KP_00,
      kp_000            = SDL_SCANCODE_KP_000,
      thousandsseparator= SDL_SCANCODE_THOUSANDSSEPARATOR,
      decimalseparator  = SDL_SCANCODE_DECIMALSEPARATOR,
      currencyunit      = SDL_SCANCODE_CURRENCYUNIT,
      currencysubunit   = SDL_SCANCODE_CURRENCYSUBUNIT,
      kp_leftparen      = SDL_SCANCODE_KP_LEFTPAREN,
      kp_rightparen     = SDL_SCANCODE_KP_RIGHTPAREN,
      kp_leftbrace      = SDL_SCANCODE_KP_LEFTBRACE,
      kp_rightbrace     = SDL_SCANCODE_KP_RIGHTBRACE,
      kp_tab            = SDL_SCANCODE_KP_TAB,
      kp_backspace      = SDL_SCANCODE_KP_BACKSPACE,
      kp_a              = SDL_SCANCODE_KP_A,
      kp_b              = SDL_SCANCODE_KP_B,
      kp_c              = SDL_SCANCODE_KP_C,
      kp_d              = SDL_SCANCODE_KP_D,
      kp_e              = SDL_SCANCODE_KP_E,
      kp_f              = SDL_SCANCODE_KP_F,
      kp_xor            = SDL_SCANCODE_KP_XOR,
      kp_power          = SDL_SCANCODE_KP_POWER,
      kp_percent        = SDL_SCANCODE_KP_PERCENT,
      kp_less           = SDL_SCANCODE_KP_LESS,
      kp_greater        = SDL_SCANCODE_KP_GREATER,
      kp_ampersand      = SDL_SCANCODE_KP_AMPERSAND,
      kp_dblampersand   = SDL_SCANCODE_KP_DBLAMPERSAND,
      kp_verticalbar    = SDL_SCANCODE_KP_VERTICALBAR,
      kp_dblverticalbar = SDL_SCANCODE_KP_DBLVERTICALBAR,
      kp_colon          = SDL_SCANCODE_KP_COLON,
      kp_hash           = SDL_SCANCODE_KP_HASH,
      kp_space          = SDL_SCANCODE_KP_SPACE,
      kp_at             = SDL_SCANCODE_KP_AT,
      kp_exclam         = SDL_SCANCODE_KP_EXCLAM,
      kp_memstore       = SDL_SCANCODE_KP_MEMSTORE,
      kp_memrecall      = SDL_SCANCODE_KP_MEMRECALL,
      kp_memclear       = SDL_SCANCODE_KP_MEMCLEAR,
      kp_memadd         = SDL_SCANCODE_KP_MEMADD,
      kp_memsubtract    = SDL_SCANCODE_KP_MEMSUBTRACT,
      kp_memmultiply    = SDL_SCANCODE_KP_MEMMULTIPLY,
      kp_memdivide      = SDL_SCANCODE_KP_MEMDIVIDE,
      kp_plusminus      = SDL_SCANCODE_KP_PLUSMINUS,
      kp_clear          = SDL_SCANCODE_KP_CLEAR,
      kp_clearentry     = SDL_SCANCODE_KP_CLEARENTRY,
      kp_binary         = SDL_SCANCODE_KP_BINARY,
      kp_octal          = SDL_SCANCODE_KP_OCTAL,
      kp_decimal        = SDL_SCANCODE_KP_DECIMAL,
      kp_hexadecimal    = SDL_SCANCODE_KP_HEXADECIMAL,
      lctrl             = SDL_SCANCODE_LCTRL,
      lshift            = SDL_SCANCODE_LSHIFT,
      lalt              = SDL_SCANCODE_LALT,
      lgui              = SDL_SCANCODE_LGUI,
      rctrl             = SDL_SCANCODE_RCTRL,
      rshift            = SDL_SCANCODE_RSHIFT,
      ralt              = SDL_SCANCODE_RALT,
      rgui              = SDL_SCANCODE_RGUI,
      mode              = SDL_SCANCODE_MODE,
      audionext         = SDL_SCANCODE_AUDIONEXT,
      audioprev         = SDL_SCANCODE_AUDIOPREV,
      audiostop         = SDL_SCANCODE_AUDIOSTOP,
      audioplay         = SDL_SCANCODE_AUDIOPLAY,
      audiomute         = SDL_SCANCODE_AUDIOMUTE,
      mediaselect       = SDL_SCANCODE_MEDIASELECT,
      www               = SDL_SCANCODE_WWW,
      mail              = SDL_SCANCODE_MAIL,
      calculator        = SDL_SCANCODE_CALCULATOR,
      computer          = SDL_SCANCODE_COMPUTER,
      ac_search         = SDL_SCANCODE_AC_SEARCH,
      ac_home           = SDL_SCANCODE_AC_HOME,
      ac_back           = SDL_SCANCODE_AC_BACK,
      ac_forward        = SDL_SCANCODE_AC_FORWARD,
      ac_stop           = SDL_SCANCODE_AC_STOP,
      ac_refresh        = SDL_SCANCODE_AC_REFRESH,
      ac_bookmarks      = SDL_SCANCODE_AC_BOOKMARKS,
      brightnessdown    = SDL_SCANCODE_BRIGHTNESSDOWN,
      brightnessup      = SDL_SCANCODE_BRIGHTNESSUP,
      displayswitch     = SDL_SCANCODE_DISPLAYSWITCH,
      kbdillumtoggle    = SDL_SCANCODE_KBDILLUMTOGGLE,
      kbdillumdown      = SDL_SCANCODE_KBDILLUMDOWN,
      kbdillumup        = SDL_SCANCODE_KBDILLUMUP,
      eject             = SDL_SCANCODE_EJECT,
      sleep             = SDL_SCANCODE_SLEEP,
      app1              = SDL_SCANCODE_APP1,
      app2              = SDL_SCANCODE_APP2,
      count             = SDL_NUM_SCANCODES
  };
  
  inline int32_t from_string(const std::string& str) noexcept {
      return SDL_GetScancodeFromName(str.c_str());
  }
  
  inline int32_t from_key(int32_t key_code) noexcept {
      return SDL_GetScancodeFromKey(key_code);
  }
  
  inline std::string to_string(int32_t scan_code) noexcept {
      return SDL_GetScancodeName(static_cast<SDL_Scancode>(scan_code));
  }
  
  inline bool is_pressed(int32_t scan_code) noexcept {
      const auto* data = SDL_GetKeyboardState(nullptr);
      return data[scan_code] != 0;
  }
  } // scan
  
  inline bool has_screen_keyboard() noexcept {
      return SDL_HasScreenKeyboardSupport() == SDL_TRUE;
  }
  
  inline void start_text_input() noexcept {
      SDL_StartTextInput();
  }
  
  inline void stop_text_input() noexcept {
      SDL_StopTextInput();
  }
  
  inline bool is_text_input_active() noexcept {
      return SDL_IsTextInputActive() == SDL_TRUE;
  }
  
  inline void text_input_rect(SDL_Rect rect) noexcept {
      SDL_SetTextInputRect(&rect);
  }
  } // sdl
  
  #endif // GUM_INPUT_KEYBOARD_HPP
  