-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// setting.cpp
-
-
-#include "keymap.h"
-#include "errormessage.h"
-#include "stringtool.h"
-#include "setting.h"
-#include <algorithm>
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Action
-
-//
-tostream &operator<<(tostream &i_ost, const Action &i_action)
-{
- return i_action.output(i_ost);
-}
-
-
-//
-ActionKey::ActionKey(const ModifiedKey &i_mk)
- : m_modifiedKey(i_mk)
-{
-}
-
-//
-Action::Type ActionKey::getType() const
-{
- return Type_key;
-}
-
-// create clone
-Action *ActionKey::clone() const
-{
- return new ActionKey(m_modifiedKey);
-}
-
-// stream output
-tostream &ActionKey::output(tostream &i_ost) const
-{
- return i_ost << m_modifiedKey;
-}
-
-//
-ActionKeySeq::ActionKeySeq(KeySeq *i_keySeq)
- : m_keySeq(i_keySeq)
-{
-}
-
-//
-Action::Type ActionKeySeq::getType() const
-{
- return Type_keySeq;
-}
-
-// create clone
-Action *ActionKeySeq::clone() const
-{
- return new ActionKeySeq(m_keySeq);
-}
-
-// stream output
-tostream &ActionKeySeq::output(tostream &i_ost) const
-{
- return i_ost << _T("$") << m_keySeq->getName();
-}
-
-//
-ActionFunction::ActionFunction(FunctionData *i_functionData,
- Modifier i_modifier)
- : m_functionData(i_functionData),
- m_modifier(i_modifier)
-{
-}
-
-//
-ActionFunction::~ActionFunction()
-{
- delete m_functionData;
-}
-
-//
-Action::Type ActionFunction::getType() const
-{
- return Type_function;
-}
-
-// create clone
-Action *ActionFunction::clone() const
-{
- return new ActionFunction(m_functionData->clone(), m_modifier);
-}
-
-// stream output
-tostream &ActionFunction::output(tostream &i_ost) const
-{
- return i_ost << m_modifier << m_functionData;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// KeySeq
-
-
-void KeySeq::copy()
-{
- for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
- (*i) = (*i)->clone();
-}
-
-
-void KeySeq::clear()
-{
- for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
- delete (*i);
-}
-
-
-KeySeq::KeySeq(const tstringi &i_name)
- : m_name(i_name),
- m_mode(Modifier::Type_KEYSEQ)
-{
-}
-
-
-KeySeq::KeySeq(const KeySeq &i_ks)
- : m_actions(i_ks.m_actions),
- m_name(i_ks.m_name),
- m_mode(i_ks.m_mode)
-{
- copy();
-}
-
-
-KeySeq::~KeySeq()
-{
- clear();
-}
-
-
-KeySeq &KeySeq::operator=(const KeySeq &i_ks)
-{
- if (this != &i_ks)
- {
- clear();
- m_actions = i_ks.m_actions;
- m_mode = i_ks.m_mode;
- copy();
- }
- return *this;
-}
-
-
-KeySeq &KeySeq::add(const Action &i_action)
-{
- m_actions.push_back(i_action.clone());
- return *this;
-}
-
-
-/// get the first modified key of this key sequence
-ModifiedKey KeySeq::getFirstModifiedKey() const
-{
- if (0 < m_actions.size())
- {
- const Action *a = m_actions.front();
- switch (a->getType())
- {
- case Action::Type_key:
- return reinterpret_cast<const ActionKey *>(a)->m_modifiedKey;
- case Action::Type_keySeq:
- return reinterpret_cast<const ActionKeySeq *>(a)->
- m_keySeq->getFirstModifiedKey();
- default:
- break;
- }
- }
- return ModifiedKey(); // failed
-}
-
-
-// stream output
-tostream &operator<<(tostream &i_ost, const KeySeq &i_ks)
-{
- for (KeySeq::Actions::const_iterator
- i = i_ks.m_actions.begin(); i != i_ks.m_actions.end(); ++ i)
- i_ost << **i << _T(" ");
- return i_ost;
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Keymap
-
-
-Keymap::KeyAssignments &Keymap::getKeyAssignments(const ModifiedKey &i_mk)
-{
- ASSERT(1 <= i_mk.m_key->getScanCodesSize());
- return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
- HASHED_KEY_ASSIGNMENT_SIZE];
-}
-
-const Keymap::KeyAssignments &
-Keymap::getKeyAssignments(const ModifiedKey &i_mk) const
-{
- ASSERT(1 <= i_mk.m_key->getScanCodesSize());
- return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
- HASHED_KEY_ASSIGNMENT_SIZE];
-}
-
-
-Keymap::Keymap(Type i_type,
- const tstringi &i_name,
- const tstringi &i_windowClass,
- const tstringi &i_windowTitle,
- KeySeq *i_defaultKeySeq,
- Keymap *i_parentKeymap)
- : m_type(i_type),
- m_name(i_name),
- m_defaultKeySeq(i_defaultKeySeq),
- m_parentKeymap(i_parentKeymap),
- m_windowClass(_T(".*")),
- m_windowTitle(_T(".*"))
-{
- if (i_type == Type_windowAnd || i_type == Type_windowOr)
- try
- {
- tregex::flag_type f = (tregex::normal |
- tregex::icase |
- tregex::use_except);
- if (!i_windowClass.empty())
- m_windowClass.assign(i_windowClass, f);
- if (!i_windowTitle.empty())
- m_windowTitle.assign(i_windowTitle, f);
- }
- catch (boost::bad_expression &i_e)
- {
- throw ErrorMessage() << i_e.what();
- }
-}
-
-
-// add a key assignment;
-void Keymap::addAssignment(const ModifiedKey &i_mk, KeySeq *i_keySeq)
-{
- KeyAssignments &ka = getKeyAssignments(i_mk);
- for (KeyAssignments::iterator i = ka.begin(); i != ka.end(); ++ i)
- if ((*i).m_modifiedKey == i_mk)
- {
- (*i).m_keySeq = i_keySeq;
- return;
- }
- ka.push_front(KeyAssignment(i_mk, i_keySeq));
-}
-
-
-// add modifier
-void Keymap::addModifier(Modifier::Type i_mt, AssignOperator i_ao,
- AssignMode i_am, Key *i_key)
-{
- if (i_ao == AO_new)
- m_modAssignments[i_mt].clear();
- else
- {
- for (ModAssignments::iterator i = m_modAssignments[i_mt].begin();
- i != m_modAssignments[i_mt].end(); ++ i)
- if ((*i).m_key == i_key)
- {
- (*i).m_assignOperator = i_ao;
- (*i).m_assignMode = i_am;
- return;
- }
- }
- ModAssignment ma;
- ma.m_assignOperator = i_ao;
- ma.m_assignMode = i_am;
- ma.m_key = i_key;
- m_modAssignments[i_mt].push_back(ma);
-}
-
-
-// search
-const Keymap::KeyAssignment *
-Keymap::searchAssignment(const ModifiedKey &i_mk) const
-{
- const KeyAssignments &ka = getKeyAssignments(i_mk);
- for (KeyAssignments::const_iterator i = ka.begin(); i != ka.end(); ++ i)
- if ((*i).m_modifiedKey.m_key == i_mk.m_key &&
- (*i).m_modifiedKey.m_modifier.doesMatch(i_mk.m_modifier))
- return &(*i);
- return NULL;
-}
-
-
-// does same window
-bool Keymap::doesSameWindow(const tstringi i_className,
- const tstringi &i_titleName)
-{
- if (m_type == Type_keymap)
- return false;
-
- tsmatch what;
- if (boost::regex_search(i_className, what, m_windowClass))
- {
- if (m_type == Type_windowAnd)
- return boost::regex_search(i_titleName, what, m_windowTitle);
- else // type == Type_windowOr
- return true;
- }
- else
- {
- if (m_type == Type_windowAnd)
- return false;
- else // type == Type_windowOr
- return boost::regex_search(i_titleName, what, m_windowTitle);
- }
-}
-
-
-// adjust modifier
-void Keymap::adjustModifier(Keyboard &i_keyboard)
-{
- for (size_t i = 0; i < NUMBER_OF(m_modAssignments); ++ i)
- {
- ModAssignments mos;
- if (m_parentKeymap)
- mos = m_parentKeymap->m_modAssignments[i];
- else
- {
- // set default modifiers
- if (i < Modifier::Type_BASIC)
- {
- Keyboard::Mods mods =
- i_keyboard.getModifiers(static_cast<Modifier::Type>(i));
- for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)
- {
- ModAssignment ma;
- ma.m_assignOperator = AO_add;
- ma.m_assignMode = AM_normal;
- ma.m_key = *j;
- mos.push_back(ma);
- }
- }
- }
-
- // mod adjust
- for (ModAssignments::iterator mai = m_modAssignments[i].begin();
- mai != m_modAssignments[i].end(); ++ mai)
- {
- ModAssignment ma = *mai;
- ma.m_assignOperator = AO_new;
- switch ((*mai).m_assignOperator)
- {
- case AO_new:
- {
- mos.clear();
- mos.push_back(ma);
- break;
- }
- case AO_add:
- {
- mos.push_back(ma);
- break;
- }
- case AO_sub:
- {
- for (ModAssignments::iterator j = mos.begin();
- j != mos.end(); ++ j)
- if ((*j).m_key == ma.m_key)
- {
- mos.erase(j);
- break;
- }
- break;
- }
- case AO_overwrite:
- {
- for (ModAssignments::iterator j = mos.begin();
- j != mos.end(); ++ j)
- (*j).m_assignMode = (*mai).m_assignMode;
- break;
- }
- }
- }
-
- // erase redundant modifiers
- for (ModAssignments::iterator j = mos.begin(); j != mos.end(); ++ j)
- {
- ModAssignments::iterator k;
- for (k = j, ++ k; k != mos.end(); ++ k)
- if ((*k).m_key == (*j).m_key)
- break;
- if (k != mos.end())
- {
- k = j;
- ++ j;
- mos.erase(k);
- break;
- }
- }
-
- m_modAssignments[i] = mos;
- }
-}
-
-
-// describe
-void Keymap::describe(tostream &i_ost, DescribeParam *i_dp) const
-{
- // Is this keymap already described ?
- {
- DescribeParam::DescribedKeymap::iterator
- i = std::find(i_dp->m_dkeymap.begin(), i_dp->m_dkeymap.end(), this);
- if (i != i_dp->m_dkeymap.end())
- return; // yes!
- i_dp->m_dkeymap.push_back(this);
- }
-
- switch (m_type)
- {
- case Type_keymap:
- i_ost << _T("keymap ") << m_name;
- break;
- case Type_windowAnd:
- i_ost << _T("window ") << m_name << _T(" ");
- if (m_windowTitle.str() == _T(".*"))
- i_ost << _T("/") << m_windowClass.str() << _T("/");
- else
- i_ost << _T("( /") << m_windowClass.str() << _T("/ && /")
- << m_windowTitle.str() << _T("/ )");
- break;
- case Type_windowOr:
- i_ost << _T("window ") << m_name << _T(" ( /")
- << m_windowClass.str() << _T("/ || /") << m_windowTitle.str()
- << _T("/ )");
- break;
- }
- if (m_parentKeymap)
- i_ost << _T(" : ") << m_parentKeymap->m_name;
- i_ost << _T(" = ") << *m_defaultKeySeq << std::endl;
-
- // describe modifiers
- if (i_dp->m_doesDescribeModifiers)
- {
- for (int t = Modifier::Type_begin; t != Modifier::Type_end; ++ t)
- {
- Modifier::Type type = static_cast<Modifier::Type>(t);
- const Keymap::ModAssignments &ma = getModAssignments(type);
- if (ma.size())
- {
- i_ost << _T(" mod ") << type << _T("\t= ");
- for (Keymap::ModAssignments::const_iterator
- j = ma.begin(); j != ma.end(); ++ j)
- {
- switch (j->m_assignMode)
- {
- case Keymap::AM_true: i_ost << _T("!"); break;
- case Keymap::AM_oneShot: i_ost << _T("!!"); break;
- case Keymap::AM_oneShotRepeatable: i_ost << _T("!!!"); break;
- default:
- break;
- }
- i_ost << *j->m_key << _T(" ");
- }
- i_ost << std::endl;
- }
- }
- i_dp->m_doesDescribeModifiers = false;
- }
-
- typedef std::vector<KeyAssignment> SortedKeyAssignments;
- SortedKeyAssignments ska;
- for (size_t i = 0; i < HASHED_KEY_ASSIGNMENT_SIZE; ++ i)
- {
- const KeyAssignments &ka = m_hashedKeyAssignments[i];
- for (KeyAssignments::const_iterator j = ka.begin(); j != ka.end(); ++ j)
- ska.push_back(*j);
- }
- std::sort(ska.begin(), ska.end());
- for (SortedKeyAssignments::iterator i = ska.begin(); i != ska.end(); ++ i)
- {
- // Is this key assignment already described ?
- DescribeParam::DescribedKeys::iterator
- j = std::find(i_dp->m_dk.begin(), i_dp->m_dk.end(), i->m_modifiedKey);
- if (j != i_dp->m_dk.end())
- continue; // yes!
-
- // check if the key is an event
- Key **e;
- for (e = Event::events; *e; ++ e)
- if (i->m_modifiedKey.m_key == *e)
- break;
- if (*e)
- i_ost << _T(" event ") << *i->m_modifiedKey.m_key;
- else
- i_ost << _T(" key ") << i->m_modifiedKey;
- i_ost << _T("\t= ") << *i->m_keySeq << std::endl;
- i_dp->m_dk.push_back(i->m_modifiedKey);
- }
-
- i_ost << std::endl;
-
- if (m_parentKeymap)
- m_parentKeymap->describe(i_ost, i_dp);
-}
-
-// set default keySeq and parent keymap if default keySeq has not been set
-bool Keymap::setIfNotYet(KeySeq *i_keySeq, Keymap *i_parentKeymap)
-{
- if (m_defaultKeySeq)
- return false;
- m_defaultKeySeq = i_keySeq;
- m_parentKeymap = i_parentKeymap;
- return true;
-}
-
-// stream output
-extern tostream &operator<<(tostream &i_ost, const Keymap *i_keymap)
-{
- return i_ost << i_keymap->getName();
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Keymaps
-
-
-Keymaps::Keymaps()
-{
-}
-
-
-// search by name
-Keymap *Keymaps::searchByName(const tstringi &i_name)
-{
- for (KeymapList::iterator
- i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
- if ((*i).getName() == i_name)
- return &*i;
- return NULL;
-}
-
-
-// search window
-void Keymaps::searchWindow(KeymapPtrList *o_keymapPtrList,
- const tstringi &i_className,
- const tstringi &i_titleName)
-{
- o_keymapPtrList->clear();
- for (KeymapList::iterator
- i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
- if ((*i).doesSameWindow(i_className, i_titleName))
- o_keymapPtrList->push_back(&(*i));
-}
-
-
-// add keymap
-Keymap *Keymaps::add(const Keymap &i_keymap)
-{
- if (Keymap *k = searchByName(i_keymap.getName()))
- return k;
- m_keymapList.push_front(i_keymap);
- return &m_keymapList.front();
-}
-
-
-// adjust modifier
-void Keymaps::adjustModifier(Keyboard &i_keyboard)
-{
- for (KeymapList::reverse_iterator i = m_keymapList.rbegin();
- i != m_keymapList.rend(); ++ i)
- (*i).adjustModifier(i_keyboard);
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// KeySeqs
-
-
-// add a named keyseq (name can be empty)
-KeySeq *KeySeqs::add(const KeySeq &i_keySeq)
-{
- if (!i_keySeq.getName().empty())
- {
- KeySeq *ks = searchByName(i_keySeq.getName());
- if (ks)
- return &(*ks = i_keySeq);
- }
- m_keySeqList.push_front(i_keySeq);
- return &m_keySeqList.front();
-}
-
-
-// search by name
-KeySeq *KeySeqs::searchByName(const tstringi &i_name)
-{
- for (KeySeqList::iterator
- i = m_keySeqList.begin(); i != m_keySeqList.end(); ++ i)
- if ((*i).getName() == i_name)
- return &(*i);
- return NULL;
-}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// setting.cpp\r
+\r
+\r
+#include "keymap.h"\r
+#include "errormessage.h"\r
+#include "stringtool.h"\r
+#include "setting.h"\r
+#include <algorithm>\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Action\r
+\r
+//\r
+tostream &operator<<(tostream &i_ost, const Action &i_action)\r
+{\r
+ return i_action.output(i_ost);\r
+}\r
+\r
+\r
+//\r
+ActionKey::ActionKey(const ModifiedKey &i_mk)\r
+ : m_modifiedKey(i_mk)\r
+{\r
+}\r
+\r
+//\r
+Action::Type ActionKey::getType() const\r
+{\r
+ return Type_key;\r
+}\r
+\r
+// create clone\r
+Action *ActionKey::clone() const\r
+{\r
+ return new ActionKey(m_modifiedKey);\r
+}\r
+\r
+// stream output\r
+tostream &ActionKey::output(tostream &i_ost) const\r
+{\r
+ return i_ost << m_modifiedKey;\r
+}\r
+\r
+//\r
+ActionKeySeq::ActionKeySeq(KeySeq *i_keySeq)\r
+ : m_keySeq(i_keySeq)\r
+{\r
+}\r
+\r
+//\r
+Action::Type ActionKeySeq::getType() const\r
+{\r
+ return Type_keySeq;\r
+}\r
+\r
+// create clone\r
+Action *ActionKeySeq::clone() const\r
+{\r
+ return new ActionKeySeq(m_keySeq);\r
+}\r
+\r
+// stream output\r
+tostream &ActionKeySeq::output(tostream &i_ost) const\r
+{\r
+ return i_ost << _T("$") << m_keySeq->getName();\r
+}\r
+\r
+//\r
+ActionFunction::ActionFunction(FunctionData *i_functionData,\r
+ Modifier i_modifier)\r
+ : m_functionData(i_functionData),\r
+ m_modifier(i_modifier)\r
+{\r
+}\r
+\r
+//\r
+ActionFunction::~ActionFunction()\r
+{\r
+ delete m_functionData;\r
+}\r
+\r
+//\r
+Action::Type ActionFunction::getType() const\r
+{\r
+ return Type_function;\r
+}\r
+\r
+// create clone\r
+Action *ActionFunction::clone() const\r
+{\r
+ return new ActionFunction(m_functionData->clone(), m_modifier);\r
+}\r
+\r
+// stream output\r
+tostream &ActionFunction::output(tostream &i_ost) const\r
+{\r
+ return i_ost << m_modifier << m_functionData;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// KeySeq\r
+\r
+\r
+void KeySeq::copy()\r
+{\r
+ for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)\r
+ (*i) = (*i)->clone();\r
+}\r
+\r
+\r
+void KeySeq::clear()\r
+{\r
+ for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)\r
+ delete (*i);\r
+}\r
+\r
+\r
+KeySeq::KeySeq(const tstringi &i_name)\r
+ : m_name(i_name),\r
+ m_mode(Modifier::Type_KEYSEQ)\r
+{\r
+}\r
+\r
+\r
+KeySeq::KeySeq(const KeySeq &i_ks)\r
+ : m_actions(i_ks.m_actions),\r
+ m_name(i_ks.m_name),\r
+ m_mode(i_ks.m_mode)\r
+{\r
+ copy();\r
+}\r
+\r
+\r
+KeySeq::~KeySeq()\r
+{\r
+ clear();\r
+}\r
+\r
+\r
+KeySeq &KeySeq::operator=(const KeySeq &i_ks)\r
+{\r
+ if (this != &i_ks) {\r
+ clear();\r
+ m_actions = i_ks.m_actions;\r
+ m_mode = i_ks.m_mode;\r
+ copy();\r
+ }\r
+ return *this;\r
+}\r
+\r
+\r
+KeySeq &KeySeq::add(const Action &i_action)\r
+{\r
+ m_actions.push_back(i_action.clone());\r
+ return *this;\r
+}\r
+\r
+\r
+/// get the first modified key of this key sequence\r
+ModifiedKey KeySeq::getFirstModifiedKey() const\r
+{\r
+ if (0 < m_actions.size()) {\r
+ const Action *a = m_actions.front();\r
+ switch (a->getType()) {\r
+ case Action::Type_key:\r
+ return reinterpret_cast<const ActionKey *>(a)->m_modifiedKey;\r
+ case Action::Type_keySeq:\r
+ return reinterpret_cast<const ActionKeySeq *>(a)->\r
+ m_keySeq->getFirstModifiedKey();\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ return ModifiedKey(); // failed\r
+}\r
+\r
+\r
+// stream output\r
+tostream &operator<<(tostream &i_ost, const KeySeq &i_ks)\r
+{\r
+ for (KeySeq::Actions::const_iterator\r
+ i = i_ks.m_actions.begin(); i != i_ks.m_actions.end(); ++ i)\r
+ i_ost << **i << _T(" ");\r
+ return i_ost;\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Keymap\r
+\r
+\r
+Keymap::KeyAssignments &Keymap::getKeyAssignments(const ModifiedKey &i_mk)\r
+{\r
+ ASSERT(1 <= i_mk.m_key->getScanCodesSize());\r
+ return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %\r
+ HASHED_KEY_ASSIGNMENT_SIZE];\r
+}\r
+\r
+const Keymap::KeyAssignments &\r
+Keymap::getKeyAssignments(const ModifiedKey &i_mk) const\r
+{\r
+ ASSERT(1 <= i_mk.m_key->getScanCodesSize());\r
+ return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %\r
+ HASHED_KEY_ASSIGNMENT_SIZE];\r
+}\r
+\r
+\r
+Keymap::Keymap(Type i_type,\r
+ const tstringi &i_name,\r
+ const tstringi &i_windowClass,\r
+ const tstringi &i_windowTitle,\r
+ KeySeq *i_defaultKeySeq,\r
+ Keymap *i_parentKeymap)\r
+ : m_type(i_type),\r
+ m_name(i_name),\r
+ m_defaultKeySeq(i_defaultKeySeq),\r
+ m_parentKeymap(i_parentKeymap),\r
+ m_windowClass(_T(".*")),\r
+ m_windowTitle(_T(".*"))\r
+{\r
+ if (i_type == Type_windowAnd || i_type == Type_windowOr)\r
+ try {\r
+ tregex::flag_type f = (tregex::normal |\r
+ tregex::icase);\r
+ if (!i_windowClass.empty())\r
+ m_windowClass.assign(i_windowClass, f);\r
+ if (!i_windowTitle.empty())\r
+ m_windowTitle.assign(i_windowTitle, f);\r
+ } catch (boost::bad_expression &i_e) {\r
+ throw ErrorMessage() << i_e.what();\r
+ }\r
+}\r
+\r
+\r
+// add a key assignment;\r
+void Keymap::addAssignment(const ModifiedKey &i_mk, KeySeq *i_keySeq)\r
+{\r
+ KeyAssignments &ka = getKeyAssignments(i_mk);\r
+ for (KeyAssignments::iterator i = ka.begin(); i != ka.end(); ++ i)\r
+ if ((*i).m_modifiedKey == i_mk) {\r
+ (*i).m_keySeq = i_keySeq;\r
+ return;\r
+ }\r
+ ka.push_front(KeyAssignment(i_mk, i_keySeq));\r
+}\r
+\r
+\r
+// add modifier\r
+void Keymap::addModifier(Modifier::Type i_mt, AssignOperator i_ao,\r
+ AssignMode i_am, Key *i_key)\r
+{\r
+ if (i_ao == AO_new)\r
+ m_modAssignments[i_mt].clear();\r
+ else {\r
+ for (ModAssignments::iterator i = m_modAssignments[i_mt].begin();\r
+ i != m_modAssignments[i_mt].end(); ++ i)\r
+ if ((*i).m_key == i_key) {\r
+ (*i).m_assignOperator = i_ao;\r
+ (*i).m_assignMode = i_am;\r
+ return;\r
+ }\r
+ }\r
+ ModAssignment ma;\r
+ ma.m_assignOperator = i_ao;\r
+ ma.m_assignMode = i_am;\r
+ ma.m_key = i_key;\r
+ m_modAssignments[i_mt].push_back(ma);\r
+}\r
+\r
+\r
+// search\r
+const Keymap::KeyAssignment *\r
+Keymap::searchAssignment(const ModifiedKey &i_mk) const\r
+{\r
+ const KeyAssignments &ka = getKeyAssignments(i_mk);\r
+ for (KeyAssignments::const_iterator i = ka.begin(); i != ka.end(); ++ i)\r
+ if ((*i).m_modifiedKey.m_key == i_mk.m_key &&\r
+ (*i).m_modifiedKey.m_modifier.doesMatch(i_mk.m_modifier))\r
+ return &(*i);\r
+ return NULL;\r
+}\r
+\r
+\r
+// does same window\r
+bool Keymap::doesSameWindow(const tstringi i_className,\r
+ const tstringi &i_titleName)\r
+{\r
+ if (m_type == Type_keymap)\r
+ return false;\r
+\r
+ tsmatch what;\r
+ if (boost::regex_search(i_className, what, m_windowClass)) {\r
+ if (m_type == Type_windowAnd)\r
+ return boost::regex_search(i_titleName, what, m_windowTitle);\r
+ else // type == Type_windowOr\r
+ return true;\r
+ } else {\r
+ if (m_type == Type_windowAnd)\r
+ return false;\r
+ else // type == Type_windowOr\r
+ return boost::regex_search(i_titleName, what, m_windowTitle);\r
+ }\r
+}\r
+\r
+\r
+// adjust modifier\r
+void Keymap::adjustModifier(Keyboard &i_keyboard)\r
+{\r
+ for (size_t i = 0; i < NUMBER_OF(m_modAssignments); ++ i) {\r
+ ModAssignments mos;\r
+ if (m_parentKeymap)\r
+ mos = m_parentKeymap->m_modAssignments[i];\r
+ else {\r
+ // set default modifiers\r
+ if (i < Modifier::Type_BASIC) {\r
+ Keyboard::Mods mods =\r
+ i_keyboard.getModifiers(static_cast<Modifier::Type>(i));\r
+ for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j) {\r
+ ModAssignment ma;\r
+ ma.m_assignOperator = AO_add;\r
+ ma.m_assignMode = AM_normal;\r
+ ma.m_key = *j;\r
+ mos.push_back(ma);\r
+ }\r
+ }\r
+ }\r
+\r
+ // mod adjust\r
+ for (ModAssignments::iterator mai = m_modAssignments[i].begin();\r
+ mai != m_modAssignments[i].end(); ++ mai) {\r
+ ModAssignment ma = *mai;\r
+ ma.m_assignOperator = AO_new;\r
+ switch ((*mai).m_assignOperator) {\r
+ case AO_new: {\r
+ mos.clear();\r
+ mos.push_back(ma);\r
+ break;\r
+ }\r
+ case AO_add: {\r
+ mos.push_back(ma);\r
+ break;\r
+ }\r
+ case AO_sub: {\r
+ for (ModAssignments::iterator j = mos.begin();\r
+ j != mos.end(); ++ j)\r
+ if ((*j).m_key == ma.m_key) {\r
+ mos.erase(j);\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+ case AO_overwrite: {\r
+ for (ModAssignments::iterator j = mos.begin();\r
+ j != mos.end(); ++ j)\r
+ (*j).m_assignMode = (*mai).m_assignMode;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ // erase redundant modifiers\r
+ for (ModAssignments::iterator j = mos.begin(); j != mos.end(); ++ j) {\r
+ ModAssignments::iterator k;\r
+ for (k = j, ++ k; k != mos.end(); ++ k)\r
+ if ((*k).m_key == (*j).m_key)\r
+ break;\r
+ if (k != mos.end()) {\r
+ k = j;\r
+ ++ j;\r
+ mos.erase(k);\r
+ break;\r
+ }\r
+ }\r
+\r
+ m_modAssignments[i] = mos;\r
+ }\r
+}\r
+\r
+\r
+// describe\r
+void Keymap::describe(tostream &i_ost, DescribeParam *i_dp) const\r
+{\r
+ // Is this keymap already described ?\r
+ {\r
+ DescribeParam::DescribedKeymap::iterator\r
+ i = std::find(i_dp->m_dkeymap.begin(), i_dp->m_dkeymap.end(), this);\r
+ if (i != i_dp->m_dkeymap.end())\r
+ return; // yes!\r
+ i_dp->m_dkeymap.push_back(this);\r
+ }\r
+\r
+ switch (m_type) {\r
+ case Type_keymap:\r
+ i_ost << _T("keymap ") << m_name;\r
+ break;\r
+ case Type_windowAnd:\r
+ i_ost << _T("window ") << m_name << _T(" ");\r
+ if (m_windowTitle.str() == _T(".*"))\r
+ i_ost << _T("/") << m_windowClass.str() << _T("/");\r
+ else\r
+ i_ost << _T("( /") << m_windowClass.str() << _T("/ && /")\r
+ << m_windowTitle.str() << _T("/ )");\r
+ break;\r
+ case Type_windowOr:\r
+ i_ost << _T("window ") << m_name << _T(" ( /")\r
+ << m_windowClass.str() << _T("/ || /") << m_windowTitle.str()\r
+ << _T("/ )");\r
+ break;\r
+ }\r
+ if (m_parentKeymap)\r
+ i_ost << _T(" : ") << m_parentKeymap->m_name;\r
+ i_ost << _T(" = ") << *m_defaultKeySeq << std::endl;\r
+\r
+ // describe modifiers\r
+ if (i_dp->m_doesDescribeModifiers) {\r
+ for (int t = Modifier::Type_begin; t != Modifier::Type_end; ++ t) {\r
+ Modifier::Type type = static_cast<Modifier::Type>(t);\r
+ const Keymap::ModAssignments &ma = getModAssignments(type);\r
+ if (ma.size()) {\r
+ i_ost << _T(" mod ") << type << _T("\t= ");\r
+ for (Keymap::ModAssignments::const_iterator\r
+ j = ma.begin(); j != ma.end(); ++ j) {\r
+ switch (j->m_assignMode) {\r
+ case Keymap::AM_true:\r
+ i_ost << _T("!");\r
+ break;\r
+ case Keymap::AM_oneShot:\r
+ i_ost << _T("!!");\r
+ break;\r
+ case Keymap::AM_oneShotRepeatable:\r
+ i_ost << _T("!!!");\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ i_ost << *j->m_key << _T(" ");\r
+ }\r
+ i_ost << std::endl;\r
+ }\r
+ }\r
+ i_dp->m_doesDescribeModifiers = false;\r
+ }\r
+\r
+ typedef std::vector<KeyAssignment> SortedKeyAssignments;\r
+ SortedKeyAssignments ska;\r
+ for (size_t i = 0; i < HASHED_KEY_ASSIGNMENT_SIZE; ++ i) {\r
+ const KeyAssignments &ka = m_hashedKeyAssignments[i];\r
+ for (KeyAssignments::const_iterator j = ka.begin(); j != ka.end(); ++ j)\r
+ ska.push_back(*j);\r
+ }\r
+ std::sort(ska.begin(), ska.end());\r
+ for (SortedKeyAssignments::iterator i = ska.begin(); i != ska.end(); ++ i) {\r
+ // Is this key assignment already described ?\r
+ DescribeParam::DescribedKeys::iterator\r
+ j = std::find(i_dp->m_dk.begin(), i_dp->m_dk.end(), i->m_modifiedKey);\r
+ if (j != i_dp->m_dk.end())\r
+ continue; // yes!\r
+\r
+ // check if the key is an event\r
+ Key **e;\r
+ for (e = Event::events; *e; ++ e)\r
+ if (i->m_modifiedKey.m_key == *e)\r
+ break;\r
+ if (*e)\r
+ i_ost << _T(" event ") << *i->m_modifiedKey.m_key;\r
+ else\r
+ i_ost << _T(" key ") << i->m_modifiedKey;\r
+ i_ost << _T("\t= ") << *i->m_keySeq << std::endl;\r
+ i_dp->m_dk.push_back(i->m_modifiedKey);\r
+ }\r
+\r
+ i_ost << std::endl;\r
+\r
+ if (m_parentKeymap)\r
+ m_parentKeymap->describe(i_ost, i_dp);\r
+}\r
+\r
+// set default keySeq and parent keymap if default keySeq has not been set\r
+bool Keymap::setIfNotYet(KeySeq *i_keySeq, Keymap *i_parentKeymap)\r
+{\r
+ if (m_defaultKeySeq)\r
+ return false;\r
+ m_defaultKeySeq = i_keySeq;\r
+ m_parentKeymap = i_parentKeymap;\r
+ return true;\r
+}\r
+\r
+// stream output\r
+extern tostream &operator<<(tostream &i_ost, const Keymap *i_keymap)\r
+{\r
+ return i_ost << i_keymap->getName();\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// Keymaps\r
+\r
+\r
+Keymaps::Keymaps()\r
+{\r
+}\r
+\r
+\r
+// search by name\r
+Keymap *Keymaps::searchByName(const tstringi &i_name)\r
+{\r
+ for (KeymapList::iterator\r
+ i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)\r
+ if ((*i).getName() == i_name)\r
+ return &*i;\r
+ return NULL;\r
+}\r
+\r
+\r
+// search window\r
+void Keymaps::searchWindow(KeymapPtrList *o_keymapPtrList,\r
+ const tstringi &i_className,\r
+ const tstringi &i_titleName)\r
+{\r
+ o_keymapPtrList->clear();\r
+ for (KeymapList::iterator\r
+ i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)\r
+ if ((*i).doesSameWindow(i_className, i_titleName))\r
+ o_keymapPtrList->push_back(&(*i));\r
+}\r
+\r
+\r
+// add keymap\r
+Keymap *Keymaps::add(const Keymap &i_keymap)\r
+{\r
+ if (Keymap *k = searchByName(i_keymap.getName()))\r
+ return k;\r
+ m_keymapList.push_front(i_keymap);\r
+ return &m_keymapList.front();\r
+}\r
+\r
+\r
+// adjust modifier\r
+void Keymaps::adjustModifier(Keyboard &i_keyboard)\r
+{\r
+ for (KeymapList::reverse_iterator i = m_keymapList.rbegin();\r
+ i != m_keymapList.rend(); ++ i)\r
+ (*i).adjustModifier(i_keyboard);\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+// KeySeqs\r
+\r
+\r
+// add a named keyseq (name can be empty)\r
+KeySeq *KeySeqs::add(const KeySeq &i_keySeq)\r
+{\r
+ if (!i_keySeq.getName().empty()) {\r
+ KeySeq *ks = searchByName(i_keySeq.getName());\r
+ if (ks)\r
+ return &(*ks = i_keySeq);\r
+ }\r
+ m_keySeqList.push_front(i_keySeq);\r
+ return &m_keySeqList.front();\r
+}\r
+\r
+\r
+// search by name\r
+KeySeq *KeySeqs::searchByName(const tstringi &i_name)\r
+{\r
+ for (KeySeqList::iterator\r
+ i = m_keySeqList.begin(); i != m_keySeqList.end(); ++ i)\r
+ if ((*i).getName() == i_name)\r
+ return &(*i);\r
+ return NULL;\r
+}\r