25 #include <unordered_map>
31 #ifdef USE_SDL_MAINLOOP
66 if (eShift == pCheck->
eShift)
break;
else ++pCheck;
77 #if defined(USE_COCOA)
81 {K_ESCAPE,
"Escape",
"Esc"},
92 {K_MINUS,
"Minus",
"-"},
93 {K_EQUAL,
"Equal",
"="},
94 {K_BACK,
"BackSpace",
nullptr},
95 {K_TAB,
"Tab",
nullptr},
106 {K_LEFT_BRACKET,
"LeftBracket",
"["},
107 {K_RIGHT_BRACKET,
"RightBracket",
"]"},
108 {K_RETURN,
"Return",
"Ret"},
109 {K_CONTROL_L,
"LeftControl",
"LCtrl"},
119 {K_SEMICOLON,
"Semicolon",
";"},
120 {K_APOSTROPHE,
"Apostrophe",
"'"},
121 {K_GRAVE_ACCENT,
"GraveAccent",
"`"},
122 {K_SHIFT_L,
"LeftShift",
"LShift"},
123 {K_BACKSLASH,
"Backslash", R
"(\)"},
131 {K_COMMA,
"Comma",
","},
132 {K_PERIOD,
"Period",
"."},
133 {K_SLASH,
"Slash",
"/"},
134 {K_SHIFT_R,
"RightShift",
"RShift"},
135 {K_MULTIPLY,
"Multiply",
"N*"},
136 {K_ALT_L,
"LeftAlt",
"LAlt"},
137 {K_SPACE,
"Space",
"Sp"},
138 {K_CAPS,
"Capslock",
nullptr},
139 {K_F1,
"F1",
nullptr},
140 {K_F2,
"F2",
nullptr},
141 {K_F3,
"F3",
nullptr},
142 {K_F4,
"F4",
nullptr},
143 {K_F5,
"F5",
nullptr},
144 {K_F6,
"F6",
nullptr},
145 {K_F7,
"F7",
nullptr},
146 {K_F8,
"F8",
nullptr},
147 {K_F9,
"F9",
nullptr},
148 {K_F10,
"F10",
nullptr},
149 {K_NUM,
"NumLock",
"NLock"},
150 {K_SCROLL,
"ScrollLock",
"SLock"},
151 {K_NUM7,
"Num7",
"N7"},
152 {K_NUM8,
"Num8",
"N8"},
153 {K_NUM9,
"Num9",
"N9"},
154 {K_SUBTRACT,
"Subtract",
"N-"},
155 {K_NUM4,
"Num4",
"N4"},
156 {K_NUM5,
"Num5",
"N5"},
157 {K_NUM6,
"Num6",
"N6"},
158 {K_ADD,
"Add",
"N+"},
159 {K_NUM1,
"Num1",
"N1"},
160 {K_NUM2,
"Num2",
"N2"},
161 {K_NUM3,
"Num3",
"N3"},
162 {K_NUM0,
"Num0",
"N0"},
163 {K_DECIMAL,
"Decimal",
"N,"},
164 {K_86,
"|<>",
nullptr},
165 {K_F11,
"F11",
nullptr},
166 {K_F12,
"F12",
nullptr},
167 {K_NUM_RETURN,
"NumReturn",
"NRet"},
168 {K_CONTROL_R,
"RightControl",
"RCtrl"},
169 {K_DIVIDE,
"Divide",
"N/"},
170 {K_ALT_R,
"RightAlt",
"RAlt"},
171 {K_HOME,
"Home",
nullptr},
172 {K_UP,
"Up",
nullptr},
173 {K_PAGEUP,
"PageUp",
nullptr},
174 {K_LEFT,
"Left",
nullptr},
175 {K_RIGHT,
"Right",
nullptr},
176 {K_END,
"End",
nullptr},
177 {K_DOWN,
"Down",
nullptr},
178 {K_PAGEDOWN,
"PageDown",
nullptr},
179 {K_INSERT,
"Insert",
"Ins"},
180 {K_DELETE,
"Delete",
"Del"},
181 {K_PAUSE,
"Pause",
nullptr},
182 {K_WIN_L,
"LeftWin",
"LWin"},
183 {K_WIN_R,
"RightWin",
"RWin"},
184 {K_MENU,
"Menu",
nullptr},
185 {K_PRINT,
"Print",
nullptr},
186 {0x00,
nullptr,
nullptr}
191 : Key(key), dwShift(Shift), fRepeated(fIsRepeated), deviceId(deviceId)
223 if (!wheel_dir) assert(
"Attempted to record mouse wheel movement without a direction");
227 if (dwKeyParam & MK_CONTROL) key.dwShift |=
KEYS_Control;
228 if (dwKeyParam & MK_SHIFT) key.dwShift |=
KEYS_Shift;
229 if (dwKeyParam & MK_ALT) key.dwShift |=
KEYS_Alt;
241 C4KeyCode C4KeyCodeEx::GetKeyByScanCode(
const char *scan_code)
244 unsigned int scan_code_int;
245 if (sscanf(scan_code,
"$%x", &scan_code_int) != 1)
return KEY_Undefined;
246 return scan_code_int;
249 static const std::unordered_map<std::string, C4KeyCode> controllercodes =
285 if (sscanf(sName.
getData(), R
"(\x%x)", &dwRVal) == 1) return dwRVal;
287 if (*sName.
getData() ==
'$')
return GetKeyByScanCode(sName.
getData());
289 std::regex controller_re(R
"/(^Controller(\w+)$)/");
291 if (std::regex_match(sName.
getData(), matches, controller_re))
293 auto keycode_it = controllercodes.find(matches[1].str());
294 if (keycode_it != controllercodes.end())
302 is_mouse_key = !strnicmp(sName.
getData(),
"Mouse", 5);
304 is_mouse_key = !strncasecmp(sName.
getData(),
"Mouse", 5);
309 const char *key_str = sName.
getData()+5;
311 if (sscanf(key_str,
"%d", &mouse_id) == 1)
314 while (isdigit(*key_str)) ++key_str;
322 uint8_t mouseevent_id = 0;
328 else if (isdigit(*key_str))
332 if (sscanf(key_str,
"%d", &button_index) == 1)
335 while (isdigit(*key_str)) ++key_str;
341 if (!*key_str)
return KEY_Mouse(mouse_id, mouseevent_id);
353 return(pCheck->
wCode);
357 #if defined(USE_SDL_MAINLOOP)
358 SDL_Scancode
s = SDL_GetScancodeFromName(sName.
getData());
359 if (
s != SDL_SCANCODE_UNKNOWN)
return s;
404 auto it = std::find_if(controllercodes.begin(), controllercodes.end(), [wCode](
const auto &p)
406 return p.second == Key_GetGamepadEvent(wCode);
408 if (it != controllercodes.end())
419 const char *mouse_str =
"Mouse";
448 if (!fHumanReadable) {
450 return FormatString(
"$%x",
static_cast<unsigned int>(wCode));
452 #if defined(USE_WIN32_WINDOWS)
470 int len = GetKeyNameText(wCode<<16, buf, 100);
475 #elif defined (USE_COCOA)
481 return FormatString(
"\\x%x",
static_cast<unsigned int>(wCode));
482 #elif defined(USE_SDL_MAINLOOP)
485 if (name) buf.Copy(name);
486 if (!buf.getLength()) buf.Format(
"\\x%lx", wCode);
489 return FormatString(
"$%x",
static_cast<unsigned int>(wCode));
527 DWORD dwSetShift = 0;
543 dwSetShift |= eAddState;
570 pOutBuf->
Take(std::move(sCode));
612 return k == K_CONTROL_L || k == K_SHIFT_L || k == K_ALT_L ||
613 k == K_CONTROL_R || k == K_SHIFT_R || k == K_ALT_R;
620 : Scope(Scope), Name(), uiPriority(uiPriority), iRef(0), is_down(false)
635 : DefaultCodes(
std::move(rDefCodes)), Scope(Scope), Name(), uiPriority(uiPriority), iRef(0), is_down(false)
648 : Codes(rCpy.Codes), DefaultCodes(rCpy.DefaultCodes), Scope(rCpy.Scope), Name(), uiPriority(rCpy.uiPriority), iRef(0), is_down(false)
671 for (
const auto &code : codes)
680 assert(Name == pByKey->Name);
682 if (pByKey->DefaultCodes.size()) DefaultCodes = pByKey->DefaultCodes;
683 if (pByKey->Codes.size()) Codes = pByKey->Codes;
685 if (pByKey->uiPriority !=
PRIO_None) uiPriority = pByKey->uiPriority;
716 if (callback->OnKeyEvent(key, eEv))
727 :
C4CustomKey(DefCode, szName, Scope, pCallback, uiPriority)
736 :
C4CustomKey(rDefCodes, szName, Scope, pCallback, uiPriority)
763 for (KeyNameMap::const_iterator i = KeysByName.begin(); i != KeysByName.end(); ++i)
773 assert(pKey->
GetCodes() == rNewCodes);
775 C4CustomKey::CodeList::const_iterator iCode;
776 for (iCode = rOldCodes.begin(); iCode != rOldCodes.end(); ++iCode)
779 if (std::find(rNewCodes.begin(), rNewCodes.end(), *iCode) != rNewCodes.end())
continue;
780 std::pair<KeyCodeMap::iterator, KeyCodeMap::iterator> KeyRange = KeysByCode.equal_range((*iCode).Key);
781 for (KeyCodeMap::iterator i = KeyRange.first; i != KeyRange.second; ++i)
782 if (i->second == pKey)
789 for (iCode = rNewCodes.begin(); iCode != rNewCodes.end(); ++iCode)
792 if (std::find(rOldCodes.begin(), rOldCodes.end(), *iCode) != rOldCodes.end())
continue;
793 KeysByCode.insert(std::make_pair((*iCode).Key, pKey));
799 assert(pRegKey);
if (!pRegKey)
return;
811 if (!(OldCodes == rNewCodes)) UpdateKeyCodes(pDupKey, OldCodes, rNewCodes);
819 for (C4CustomKey::CodeList::const_iterator i = pRegKey->
GetCodes().begin(); i != pRegKey->
GetCodes().end(); ++i)
821 KeysByCode.insert(std::make_pair((*i).Key, pRegKey));
829 KeyNameMap::iterator in = KeysByName.find(rsName.
getData());
830 if (in == KeysByName.end())
return;
832 KeysByName.erase(in);
834 for (C4CustomKey::CodeList::const_iterator iCode = pKey->
GetCodes().begin(); iCode != pKey->
GetCodes().end(); ++iCode)
836 std::pair<KeyCodeMap::iterator, KeyCodeMap::iterator> KeyRange = KeysByCode.equal_range((*iCode).Key);
837 for (KeyCodeMap::iterator i = KeyRange.first; i != KeyRange.second; ++i)
838 if (i->second == pKey)
851 KeyNameMap::iterator in = KeysByName.find(pUnregKey->
GetName().
getData());
852 if (in == KeysByName.end())
return;
855 if (pKey != pUnregKey)
873 LastKeyExtraData.
iStrength = (iStrength >= 0) ? iStrength : ((InEvent !=
KEYEV_Up) * 100);
876 const int32_t iKeyRangeMax = 5;
877 int32_t iKeyRangeCnt=0, j;
879 FallbackKeys[iKeyRangeCnt++] = InKey.
Key;
891 std::pair<KeyCodeMap::iterator, KeyCodeMap::iterator> KeyRanges[iKeyRangeMax];
892 assert(iKeyRangeCnt <= iKeyRangeMax);
893 for (int32_t i = 0; i<iKeyRangeCnt; ++i)
895 KeyRanges[i] = KeysByCode.equal_range(FallbackKeys[i]);
902 KeyCodeMap::const_iterator i;
905 for (j = 0; j < iKeyRangeCnt; ++j)
906 for (i = KeyRanges[j].first; i != KeyRanges[j].second; ++i)
908 uiCurr = i->second->GetPriority();
909 if (uiCurr > uiExecPrio && uiCurr < uiLastPrio) uiExecPrio = uiCurr;
914 for (j = 0; j < iKeyRangeCnt; ++j)
915 for (i = KeyRanges[j].first; i != KeyRanges[j].second; ++i)
926 if (pKey->
Execute(InEvent, InKey))
930 uiLastPrio = uiExecPrio;
943 for (KeyNameMap::const_iterator i = KeysByName.begin(); i != KeysByName.end(); ++i)
947 pComp->
Value(*i->second);
952 if (!(OldCodes == rNewCodes)) UpdateKeyCodes(i->second, OldCodes, rNewCodes);
980 KeyNameMap::const_iterator i = KeysByName.find(szKeyName);
981 if (i == KeysByName.end())
return nullptr;
else return (*i).second;
990 if ((
size_t)iIndex < codes.size())
const char * KeycodeToString(C4KeyCode code)
const char * LoadResStr(const char *id)
bool LogF(const char *strMessage,...)
const int32_t C4MC_Button_X1Double
const int32_t C4MC_Button_X2Up
const int32_t C4MC_Button_None
const int32_t C4MC_Button_RightDown
const int32_t C4MC_Button_MiddleUp
const int32_t C4MC_Button_RightUp
const int32_t C4MC_Button_MiddleDouble
const int32_t C4MC_Button_X1Up
const int32_t C4MC_Button_MiddleDown
const int32_t C4MC_Button_RightDouble
const int32_t C4MC_Button_LeftUp
const int32_t C4MC_Button_X1Down
const int32_t C4MC_Button_LeftDown
const int32_t C4MC_Button_LeftDouble
const int32_t C4MC_Button_X2Double
const int32_t C4MC_Button_X2Down
const int32_t C4MC_Button_Wheel
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
StdSTLContainerAdapt< C > mkSTLContainerAdapt(C &rTarget, StdCompiler::Sep eSep=StdCompiler::SEP_SEP)
StdDecompileAdapt< T > mkDecompileAdapt(const T &rValue)
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
StdStrBuf FormatString(const char *szFmt,...)
const CodeList & GetCodes() const
std::vector< C4KeyCodeEx > CodeList
C4CustomKey(const C4KeyCodeEx &DefCode, const char *szName, C4KeyScope Scope, C4KeyboardCallbackInterface *pCallback, unsigned int uiPriority=PRIO_Base)
unsigned int GetPriority() const
const StdStrBuf & GetName() const
void CompileFunc(StdCompiler *pComp)
bool Execute(C4KeyEventType eEv, C4KeyCodeEx key)
void Update(const C4CustomKey *pByKey)
bool IsCodeMatched(const C4KeyCodeEx &key) const
void KillCallbacks(const C4CustomKey *pOfKey)
C4KeyScope GetScope() const
C4KeyboardInput & KeyboardInput
bool LoadEntry(const char *entry_name, char **buffer, size_t *size_info=nullptr, int zeros_to_append=0)
bool Open(const char *group_name, bool do_create=false)
class C4CustomKey * pOriginalKey
const void * getData() const
virtual bool Separator(Sep eSep=SEP_SEP)
void excCorrupt(const char *szMessage,...)
virtual void NoSeparator()
void Value(const T &rStruct)
virtual void NameEnd(bool fBreak=false)
virtual bool isDeserializer()
virtual bool Name(const char *szName)
const char * getData() const
void AppendChar(char cChar)
void Append(const char *pnData, size_t iChars)
static C4KeyCode String2KeyCode(const StdStrBuf &sName)
static C4KeyCodeEx FromC4MC(int8_t mouse_id, int32_t button, DWORD param, bool *is_down=nullptr)
static StdStrBuf KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool fShort)
StdStrBuf ToString(bool fHumanReadable, bool fShort) const
C4KeyCodeEx(C4KeyCode Key=KEY_Default, DWORD Shift=KEYS_None, bool fIsRepeated=false, int32_t deviceId=-1)
static C4KeyShiftState String2KeyShift(const StdStrBuf &sName)
static StdStrBuf KeyShift2String(C4KeyShiftState eShift)
void CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBuf=nullptr)
void CompileFunc(StdCompiler *pComp)
bool operator==(const struct C4KeyEventData &cmp) const