1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 #include "errormessage.h"
7 #include "stringtool.h"
12 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 tostream &operator<<(tostream &i_ost, const Action &i_action)
18 return i_action.output(i_ost);
23 ActionKey::ActionKey(const ModifiedKey &i_mk)
29 Action::Type ActionKey::getType() const
35 Action *ActionKey::clone() const
37 return new ActionKey(m_modifiedKey);
41 tostream &ActionKey::output(tostream &i_ost) const
43 return i_ost << m_modifiedKey;
47 ActionKeySeq::ActionKeySeq(KeySeq *i_keySeq)
53 Action::Type ActionKeySeq::getType() const
59 Action *ActionKeySeq::clone() const
61 return new ActionKeySeq(m_keySeq);
65 tostream &ActionKeySeq::output(tostream &i_ost) const
67 return i_ost << _T("$") << m_keySeq->getName();
71 ActionFunction::ActionFunction(FunctionData *i_functionData,
73 : m_functionData(i_functionData),
74 m_modifier(i_modifier)
79 ActionFunction::~ActionFunction()
81 delete m_functionData;
85 Action::Type ActionFunction::getType() const
91 Action *ActionFunction::clone() const
93 return new ActionFunction(m_functionData->clone(), m_modifier);
97 tostream &ActionFunction::output(tostream &i_ost) const
99 return i_ost << m_modifier << m_functionData;
103 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
109 for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
110 (*i) = (*i)->clone();
116 for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
121 KeySeq::KeySeq(const tstringi &i_name)
123 m_mode(Modifier::Type_KEYSEQ)
128 KeySeq::KeySeq(const KeySeq &i_ks)
129 : m_actions(i_ks.m_actions),
143 KeySeq &KeySeq::operator=(const KeySeq &i_ks)
148 m_actions = i_ks.m_actions;
149 m_mode = i_ks.m_mode;
156 KeySeq &KeySeq::add(const Action &i_action)
158 m_actions.push_back(i_action.clone());
163 /// get the first modified key of this key sequence
164 ModifiedKey KeySeq::getFirstModifiedKey() const
166 if (0 < m_actions.size())
168 const Action *a = m_actions.front();
169 switch (a->getType())
171 case Action::Type_key:
172 return reinterpret_cast<const ActionKey *>(a)->m_modifiedKey;
173 case Action::Type_keySeq:
174 return reinterpret_cast<const ActionKeySeq *>(a)->
175 m_keySeq->getFirstModifiedKey();
180 return ModifiedKey(); // failed
185 tostream &operator<<(tostream &i_ost, const KeySeq &i_ks)
187 for (KeySeq::Actions::const_iterator
188 i = i_ks.m_actions.begin(); i != i_ks.m_actions.end(); ++ i)
189 i_ost << **i << _T(" ");
194 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
198 Keymap::KeyAssignments &Keymap::getKeyAssignments(const ModifiedKey &i_mk)
200 ASSERT(1 <= i_mk.m_key->getScanCodesSize());
201 return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
202 HASHED_KEY_ASSIGNMENT_SIZE];
205 const Keymap::KeyAssignments &
206 Keymap::getKeyAssignments(const ModifiedKey &i_mk) const
208 ASSERT(1 <= i_mk.m_key->getScanCodesSize());
209 return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
210 HASHED_KEY_ASSIGNMENT_SIZE];
214 Keymap::Keymap(Type i_type,
215 const tstringi &i_name,
216 const tstringi &i_windowClass,
217 const tstringi &i_windowTitle,
218 KeySeq *i_defaultKeySeq,
219 Keymap *i_parentKeymap)
222 m_defaultKeySeq(i_defaultKeySeq),
223 m_parentKeymap(i_parentKeymap),
224 m_windowClass(_T(".*")),
225 m_windowTitle(_T(".*"))
227 if (i_type == Type_windowAnd || i_type == Type_windowOr)
230 tregex::flag_type f = (tregex::normal |
232 if (!i_windowClass.empty())
233 m_windowClass.assign(i_windowClass, f);
234 if (!i_windowTitle.empty())
235 m_windowTitle.assign(i_windowTitle, f);
237 catch (boost::bad_expression &i_e)
239 throw ErrorMessage() << i_e.what();
244 // add a key assignment;
245 void Keymap::addAssignment(const ModifiedKey &i_mk, KeySeq *i_keySeq)
247 KeyAssignments &ka = getKeyAssignments(i_mk);
248 for (KeyAssignments::iterator i = ka.begin(); i != ka.end(); ++ i)
249 if ((*i).m_modifiedKey == i_mk)
251 (*i).m_keySeq = i_keySeq;
254 ka.push_front(KeyAssignment(i_mk, i_keySeq));
259 void Keymap::addModifier(Modifier::Type i_mt, AssignOperator i_ao,
260 AssignMode i_am, Key *i_key)
263 m_modAssignments[i_mt].clear();
266 for (ModAssignments::iterator i = m_modAssignments[i_mt].begin();
267 i != m_modAssignments[i_mt].end(); ++ i)
268 if ((*i).m_key == i_key)
270 (*i).m_assignOperator = i_ao;
271 (*i).m_assignMode = i_am;
276 ma.m_assignOperator = i_ao;
277 ma.m_assignMode = i_am;
279 m_modAssignments[i_mt].push_back(ma);
284 const Keymap::KeyAssignment *
285 Keymap::searchAssignment(const ModifiedKey &i_mk) const
287 const KeyAssignments &ka = getKeyAssignments(i_mk);
288 for (KeyAssignments::const_iterator i = ka.begin(); i != ka.end(); ++ i)
289 if ((*i).m_modifiedKey.m_key == i_mk.m_key &&
290 (*i).m_modifiedKey.m_modifier.doesMatch(i_mk.m_modifier))
297 bool Keymap::doesSameWindow(const tstringi i_className,
298 const tstringi &i_titleName)
300 if (m_type == Type_keymap)
304 if (boost::regex_search(i_className, what, m_windowClass))
306 if (m_type == Type_windowAnd)
307 return boost::regex_search(i_titleName, what, m_windowTitle);
308 else // type == Type_windowOr
313 if (m_type == Type_windowAnd)
315 else // type == Type_windowOr
316 return boost::regex_search(i_titleName, what, m_windowTitle);
322 void Keymap::adjustModifier(Keyboard &i_keyboard)
324 for (size_t i = 0; i < NUMBER_OF(m_modAssignments); ++ i)
328 mos = m_parentKeymap->m_modAssignments[i];
331 // set default modifiers
332 if (i < Modifier::Type_BASIC)
334 Keyboard::Mods mods =
335 i_keyboard.getModifiers(static_cast<Modifier::Type>(i));
336 for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j)
339 ma.m_assignOperator = AO_add;
340 ma.m_assignMode = AM_normal;
348 for (ModAssignments::iterator mai = m_modAssignments[i].begin();
349 mai != m_modAssignments[i].end(); ++ mai)
351 ModAssignment ma = *mai;
352 ma.m_assignOperator = AO_new;
353 switch ((*mai).m_assignOperator)
368 for (ModAssignments::iterator j = mos.begin();
369 j != mos.end(); ++ j)
370 if ((*j).m_key == ma.m_key)
379 for (ModAssignments::iterator j = mos.begin();
380 j != mos.end(); ++ j)
381 (*j).m_assignMode = (*mai).m_assignMode;
387 // erase redundant modifiers
388 for (ModAssignments::iterator j = mos.begin(); j != mos.end(); ++ j)
390 ModAssignments::iterator k;
391 for (k = j, ++ k; k != mos.end(); ++ k)
392 if ((*k).m_key == (*j).m_key)
403 m_modAssignments[i] = mos;
409 void Keymap::describe(tostream &i_ost, DescribeParam *i_dp) const
411 // Is this keymap already described ?
413 DescribeParam::DescribedKeymap::iterator
414 i = std::find(i_dp->m_dkeymap.begin(), i_dp->m_dkeymap.end(), this);
415 if (i != i_dp->m_dkeymap.end())
417 i_dp->m_dkeymap.push_back(this);
423 i_ost << _T("keymap ") << m_name;
426 i_ost << _T("window ") << m_name << _T(" ");
427 if (m_windowTitle.str() == _T(".*"))
428 i_ost << _T("/") << m_windowClass.str() << _T("/");
430 i_ost << _T("( /") << m_windowClass.str() << _T("/ && /")
431 << m_windowTitle.str() << _T("/ )");
434 i_ost << _T("window ") << m_name << _T(" ( /")
435 << m_windowClass.str() << _T("/ || /") << m_windowTitle.str()
440 i_ost << _T(" : ") << m_parentKeymap->m_name;
441 i_ost << _T(" = ") << *m_defaultKeySeq << std::endl;
443 // describe modifiers
444 if (i_dp->m_doesDescribeModifiers)
446 for (int t = Modifier::Type_begin; t != Modifier::Type_end; ++ t)
448 Modifier::Type type = static_cast<Modifier::Type>(t);
449 const Keymap::ModAssignments &ma = getModAssignments(type);
452 i_ost << _T(" mod ") << type << _T("\t= ");
453 for (Keymap::ModAssignments::const_iterator
454 j = ma.begin(); j != ma.end(); ++ j)
456 switch (j->m_assignMode)
458 case Keymap::AM_true: i_ost << _T("!"); break;
459 case Keymap::AM_oneShot: i_ost << _T("!!"); break;
460 case Keymap::AM_oneShotRepeatable: i_ost << _T("!!!"); break;
464 i_ost << *j->m_key << _T(" ");
469 i_dp->m_doesDescribeModifiers = false;
472 typedef std::vector<KeyAssignment> SortedKeyAssignments;
473 SortedKeyAssignments ska;
474 for (size_t i = 0; i < HASHED_KEY_ASSIGNMENT_SIZE; ++ i)
476 const KeyAssignments &ka = m_hashedKeyAssignments[i];
477 for (KeyAssignments::const_iterator j = ka.begin(); j != ka.end(); ++ j)
480 std::sort(ska.begin(), ska.end());
481 for (SortedKeyAssignments::iterator i = ska.begin(); i != ska.end(); ++ i)
483 // Is this key assignment already described ?
484 DescribeParam::DescribedKeys::iterator
485 j = std::find(i_dp->m_dk.begin(), i_dp->m_dk.end(), i->m_modifiedKey);
486 if (j != i_dp->m_dk.end())
489 // check if the key is an event
491 for (e = Event::events; *e; ++ e)
492 if (i->m_modifiedKey.m_key == *e)
495 i_ost << _T(" event ") << *i->m_modifiedKey.m_key;
497 i_ost << _T(" key ") << i->m_modifiedKey;
498 i_ost << _T("\t= ") << *i->m_keySeq << std::endl;
499 i_dp->m_dk.push_back(i->m_modifiedKey);
505 m_parentKeymap->describe(i_ost, i_dp);
508 // set default keySeq and parent keymap if default keySeq has not been set
509 bool Keymap::setIfNotYet(KeySeq *i_keySeq, Keymap *i_parentKeymap)
513 m_defaultKeySeq = i_keySeq;
514 m_parentKeymap = i_parentKeymap;
519 extern tostream &operator<<(tostream &i_ost, const Keymap *i_keymap)
521 return i_ost << i_keymap->getName();
525 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
535 Keymap *Keymaps::searchByName(const tstringi &i_name)
537 for (KeymapList::iterator
538 i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
539 if ((*i).getName() == i_name)
546 void Keymaps::searchWindow(KeymapPtrList *o_keymapPtrList,
547 const tstringi &i_className,
548 const tstringi &i_titleName)
550 o_keymapPtrList->clear();
551 for (KeymapList::iterator
552 i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
553 if ((*i).doesSameWindow(i_className, i_titleName))
554 o_keymapPtrList->push_back(&(*i));
559 Keymap *Keymaps::add(const Keymap &i_keymap)
561 if (Keymap *k = searchByName(i_keymap.getName()))
563 m_keymapList.push_front(i_keymap);
564 return &m_keymapList.front();
569 void Keymaps::adjustModifier(Keyboard &i_keyboard)
571 for (KeymapList::reverse_iterator i = m_keymapList.rbegin();
572 i != m_keymapList.rend(); ++ i)
573 (*i).adjustModifier(i_keyboard);
577 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
581 // add a named keyseq (name can be empty)
582 KeySeq *KeySeqs::add(const KeySeq &i_keySeq)
584 if (!i_keySeq.getName().empty())
586 KeySeq *ks = searchByName(i_keySeq.getName());
588 return &(*ks = i_keySeq);
590 m_keySeqList.push_front(i_keySeq);
591 return &m_keySeqList.front();
596 KeySeq *KeySeqs::searchByName(const tstringi &i_name)
598 for (KeySeqList::iterator
599 i = m_keySeqList.begin(); i != m_keySeqList.end(); ++ i)
600 if ((*i).getName() == i_name)