const CKeyBindings::ActionList& CKeyBindings::GetActionList(const CKeySet& ks) const { static const ActionList empty; const ActionList* alPtr = NULL; if (ks.AnyMod()) { KeyMap::const_iterator it = bindings.find(ks); if (it == bindings.end()) { alPtr = ∅ } else { alPtr = &(it->second); } } else { // have to check for an AnyMod keyset as well as the normal one CKeySet anyMod = ks; anyMod.SetAnyBit(); KeyMap::const_iterator nit = bindings.find(ks); KeyMap::const_iterator ait = bindings.find(anyMod); const bool haveNormal = (nit != bindings.end()); const bool haveAnyMod = (ait != bindings.end()); if (!haveNormal && !haveAnyMod) { alPtr = ∅ } else if (haveNormal && !haveAnyMod) { alPtr = &(nit->second); } else if (!haveNormal && haveAnyMod) { alPtr = &(ait->second); } else { // combine the two lists (normal first) static ActionList merged; merged = nit->second; const ActionList& aal = ait->second; for (int i = 0; i < (int)aal.size(); ++i) { merged.push_back(aal[i]); } alPtr = &merged; } } if (LOG_IS_ENABLED(L_DEBUG)) { const bool isEmpty = (alPtr == &empty); LOG_L(L_DEBUG, "GetAction: %s (0x%03X)%s", ks.GetString(false).c_str(), ks.Key(), (isEmpty ? " EMPTY" : "")); if (!isEmpty) { const ActionList& al = *alPtr; for (size_t i = 0; i < al.size(); ++i) { LOG_L(L_DEBUG, " %s \"%s\"", al[i].command.c_str(), al[i].rawline.c_str()); } } } return *alPtr; }
bool CKeyBindings::Bind(const string& keystr, const string& line) { CKeySet ks; if (!ParseKeySet(keystr, ks)) { LOG_L(L_WARNING, "Bind: could not parse key: %s", keystr.c_str()); return false; } Action action(line); action.boundWith = keystr; if (action.command.empty()) { LOG_L(L_WARNING, "Bind: empty action: %s", line.c_str()); return false; } // Try to be safe, force AnyMod mode for stateful commands if (statefulCommands.find(action.command) != statefulCommands.end()) { ks.SetAnyBit(); } KeyMap::iterator it = bindings.find(ks); if (it == bindings.end()) { // new entry, push it ActionList& al = bindings[ks]; al.push_back(action); } else { if (it->first != ks) { // not a match, push it ActionList& al = it->second; al.push_back(action); } else { // an exact keyset match, check the command ActionList& al = it->second; int i; for (i = 0; i < (int)al.size(); i++) { if (action.command == al[i].command) { break; } } if (i == (int)al.size()) { // not a match, push it al.push_back(action); } } } return true; }
const CKeyBindings::ActionList& CKeyBindings::GetActionList(const CKeySet& ks) const { static const ActionList empty; const ActionList* alPtr = ∅ if (ks.AnyMod()) { KeyMap::const_iterator it = bindings.find(ks); if (it != bindings.end()) { alPtr = &(it->second); } } else { // have to check for an AnyMod keyset as well as the normal one CKeySet anyMod = ks; anyMod.SetAnyBit(); KeyMap::const_iterator nit = bindings.find(ks); KeyMap::const_iterator ait = bindings.find(anyMod); const bool haveNormal = (nit != bindings.end()); const bool haveAnyMod = (ait != bindings.end()); if (haveNormal && !haveAnyMod) { alPtr = &(nit->second); } else if (!haveNormal && haveAnyMod) { alPtr = &(ait->second); } else if (haveNormal && haveAnyMod) { // combine the two lists (normal first) static ActionList merged; //FIXME switch to thread_local when all buildbots are using >=gcc4.7 merged = nit->second; merged.insert(merged.end(), ait->second.begin(), ait->second.end()); alPtr = &merged; } } if (debugEnabled) { LOG("GetActions: hex=0x%02X acii=\"%s\":", ks.Key(), ks.GetString(false).c_str()); if (alPtr != &empty) { int i = 1; for (const auto& a: *alPtr) { LOG(" %i. action=\"%s\" rawline=\"%s\" shortcut=\"%s\"", i++, a.command.c_str(), a.rawline.c_str(), a.boundWith.c_str()); } } else { LOG(" EMPTY"); } } return *alPtr; }
const CKeyBindings::ActionList& CKeyBindings::GetActionList(const CKeySet& ks) const { static const ActionList empty; const ActionList* alPtr = NULL; if (ks.AnyMod()) { KeyMap::const_iterator it = bindings.find(ks); if (it == bindings.end()) { alPtr = ∅ } else { alPtr = &(it->second); } } else { // have to check for an AnyMod keyset as well as the normal one CKeySet anyMod = ks; anyMod.SetAnyBit(); KeyMap::const_iterator nit = bindings.find(ks); KeyMap::const_iterator ait = bindings.find(anyMod); const bool haveNormal = (nit != bindings.end()); const bool haveAnyMod = (ait != bindings.end()); if (!haveNormal && !haveAnyMod) { alPtr = ∅ } else if (haveNormal && !haveAnyMod) { alPtr = &(nit->second); } else if (!haveNormal && haveAnyMod) { alPtr = &(ait->second); } else { // combine the two lists (normal first) static ActionList merged; merged = nit->second; const ActionList& aal = ait->second; for (int i = 0; i < (int)aal.size(); ++i) { merged.push_back(aal[i]); } alPtr = &merged; } } if (debug > 0) { char buf[256]; SNPRINTF(buf, sizeof(buf), "GetAction: %s (0x%03X)", ks.GetString(false).c_str(), ks.Key()); if (alPtr == &empty) { strncat(buf, " EMPTY", sizeof(buf)); logOutput.Print("%s", buf); } else { logOutput.Print("%s", buf); const ActionList& al = *alPtr; for (int i = 0; i < (int)al.size(); ++i) { SNPRINTF(buf, sizeof(buf), " %s \"%s\"", al[i].command.c_str(), al[i].rawline.c_str()); logOutput.Print("%s", buf); } } } return *alPtr; }