1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
6 #include "errormessage.h"
\r
7 #include "stringtool.h"
\r
12 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
16 tostream &operator<<(tostream &i_ost, const Action &i_action)
\r
18 return i_action.output(i_ost);
\r
23 ActionKey::ActionKey(const ModifiedKey &i_mk)
\r
24 : m_modifiedKey(i_mk)
\r
29 Action::Type ActionKey::getType() const
\r
35 Action *ActionKey::clone() const
\r
37 return new ActionKey(m_modifiedKey);
\r
41 tostream &ActionKey::output(tostream &i_ost) const
\r
43 return i_ost << m_modifiedKey;
\r
47 ActionKeySeq::ActionKeySeq(KeySeq *i_keySeq)
\r
48 : m_keySeq(i_keySeq)
\r
53 Action::Type ActionKeySeq::getType() const
\r
59 Action *ActionKeySeq::clone() const
\r
61 return new ActionKeySeq(m_keySeq);
\r
65 tostream &ActionKeySeq::output(tostream &i_ost) const
\r
67 return i_ost << _T("$") << m_keySeq->getName();
\r
71 ActionFunction::ActionFunction(FunctionData *i_functionData,
\r
72 Modifier i_modifier)
\r
73 : m_functionData(i_functionData),
\r
74 m_modifier(i_modifier)
\r
79 ActionFunction::~ActionFunction()
\r
81 delete m_functionData;
\r
85 Action::Type ActionFunction::getType() const
\r
87 return Type_function;
\r
91 Action *ActionFunction::clone() const
\r
93 return new ActionFunction(m_functionData->clone(), m_modifier);
\r
97 tostream &ActionFunction::output(tostream &i_ost) const
\r
99 return i_ost << m_modifier << m_functionData;
\r
103 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
107 void KeySeq::copy()
\r
109 for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
\r
110 (*i) = (*i)->clone();
\r
114 void KeySeq::clear()
\r
116 for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
\r
121 KeySeq::KeySeq(const tstringi &i_name)
\r
123 m_mode(Modifier::Type_KEYSEQ)
\r
128 KeySeq::KeySeq(const KeySeq &i_ks)
\r
129 : m_actions(i_ks.m_actions),
\r
130 m_name(i_ks.m_name),
\r
131 m_mode(i_ks.m_mode)
\r
143 KeySeq &KeySeq::operator=(const KeySeq &i_ks)
\r
145 if (this != &i_ks) {
\r
147 m_actions = i_ks.m_actions;
\r
148 m_mode = i_ks.m_mode;
\r
155 KeySeq &KeySeq::add(const Action &i_action)
\r
157 m_actions.push_back(i_action.clone());
\r
162 /// get the first modified key of this key sequence
\r
163 ModifiedKey KeySeq::getFirstModifiedKey() const
\r
165 if (0 < m_actions.size()) {
\r
166 const Action *a = m_actions.front();
\r
167 switch (a->getType()) {
\r
168 case Action::Type_key:
\r
169 return reinterpret_cast<const ActionKey *>(a)->m_modifiedKey;
\r
170 case Action::Type_keySeq:
\r
171 return reinterpret_cast<const ActionKeySeq *>(a)->
\r
172 m_keySeq->getFirstModifiedKey();
\r
177 return ModifiedKey(); // failed
\r
182 tostream &operator<<(tostream &i_ost, const KeySeq &i_ks)
\r
184 for (KeySeq::Actions::const_iterator
\r
185 i = i_ks.m_actions.begin(); i != i_ks.m_actions.end(); ++ i)
\r
186 i_ost << **i << _T(" ");
\r
191 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
195 Keymap::KeyAssignments &Keymap::getKeyAssignments(const ModifiedKey &i_mk)
\r
197 ASSERT(1 <= i_mk.m_key->getScanCodesSize());
\r
198 return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
\r
199 HASHED_KEY_ASSIGNMENT_SIZE];
\r
202 const Keymap::KeyAssignments &
\r
203 Keymap::getKeyAssignments(const ModifiedKey &i_mk) const
\r
205 ASSERT(1 <= i_mk.m_key->getScanCodesSize());
\r
206 return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
\r
207 HASHED_KEY_ASSIGNMENT_SIZE];
\r
211 Keymap::Keymap(Type i_type,
\r
212 const tstringi &i_name,
\r
213 const tstringi &i_windowClass,
\r
214 const tstringi &i_windowTitle,
\r
215 KeySeq *i_defaultKeySeq,
\r
216 Keymap *i_parentKeymap)
\r
219 m_defaultKeySeq(i_defaultKeySeq),
\r
220 m_parentKeymap(i_parentKeymap),
\r
221 m_windowClass(_T(".*")),
\r
222 m_windowTitle(_T(".*"))
\r
224 if (i_type == Type_windowAnd || i_type == Type_windowOr)
\r
226 tregex::flag_type f = (tregex::normal |
\r
228 if (!i_windowClass.empty())
\r
229 m_windowClass.assign(i_windowClass, f);
\r
230 if (!i_windowTitle.empty())
\r
231 m_windowTitle.assign(i_windowTitle, f);
\r
232 } catch (boost::bad_expression &i_e) {
\r
233 throw ErrorMessage() << i_e.what();
\r
238 // add a key assignment;
\r
239 void Keymap::addAssignment(const ModifiedKey &i_mk, KeySeq *i_keySeq)
\r
241 KeyAssignments &ka = getKeyAssignments(i_mk);
\r
242 for (KeyAssignments::iterator i = ka.begin(); i != ka.end(); ++ i)
\r
243 if ((*i).m_modifiedKey == i_mk) {
\r
244 (*i).m_keySeq = i_keySeq;
\r
247 ka.push_front(KeyAssignment(i_mk, i_keySeq));
\r
252 void Keymap::addModifier(Modifier::Type i_mt, AssignOperator i_ao,
\r
253 AssignMode i_am, Key *i_key)
\r
255 if (i_ao == AO_new)
\r
256 m_modAssignments[i_mt].clear();
\r
258 for (ModAssignments::iterator i = m_modAssignments[i_mt].begin();
\r
259 i != m_modAssignments[i_mt].end(); ++ i)
\r
260 if ((*i).m_key == i_key) {
\r
261 (*i).m_assignOperator = i_ao;
\r
262 (*i).m_assignMode = i_am;
\r
267 ma.m_assignOperator = i_ao;
\r
268 ma.m_assignMode = i_am;
\r
270 m_modAssignments[i_mt].push_back(ma);
\r
275 const Keymap::KeyAssignment *
\r
276 Keymap::searchAssignment(const ModifiedKey &i_mk) const
\r
278 const KeyAssignments &ka = getKeyAssignments(i_mk);
\r
279 for (KeyAssignments::const_iterator i = ka.begin(); i != ka.end(); ++ i)
\r
280 if ((*i).m_modifiedKey.m_key == i_mk.m_key &&
\r
281 (*i).m_modifiedKey.m_modifier.doesMatch(i_mk.m_modifier))
\r
287 // does same window
\r
288 bool Keymap::doesSameWindow(const tstringi i_className,
\r
289 const tstringi &i_titleName)
\r
291 if (m_type == Type_keymap)
\r
295 if (boost::regex_search(i_className, what, m_windowClass)) {
\r
296 if (m_type == Type_windowAnd)
\r
297 return boost::regex_search(i_titleName, what, m_windowTitle);
\r
298 else // type == Type_windowOr
\r
301 if (m_type == Type_windowAnd)
\r
303 else // type == Type_windowOr
\r
304 return boost::regex_search(i_titleName, what, m_windowTitle);
\r
310 void Keymap::adjustModifier(Keyboard &i_keyboard)
\r
312 for (size_t i = 0; i < NUMBER_OF(m_modAssignments); ++ i) {
\r
313 ModAssignments mos;
\r
314 if (m_parentKeymap)
\r
315 mos = m_parentKeymap->m_modAssignments[i];
\r
317 // set default modifiers
\r
318 if (i < Modifier::Type_BASIC) {
\r
319 Keyboard::Mods mods =
\r
320 i_keyboard.getModifiers(static_cast<Modifier::Type>(i));
\r
321 for (Keyboard::Mods::iterator j = mods.begin(); j != mods.end(); ++ j) {
\r
323 ma.m_assignOperator = AO_add;
\r
324 ma.m_assignMode = AM_normal;
\r
332 for (ModAssignments::iterator mai = m_modAssignments[i].begin();
\r
333 mai != m_modAssignments[i].end(); ++ mai) {
\r
334 ModAssignment ma = *mai;
\r
335 ma.m_assignOperator = AO_new;
\r
336 switch ((*mai).m_assignOperator) {
\r
347 for (ModAssignments::iterator j = mos.begin();
\r
348 j != mos.end(); ++ j)
\r
349 if ((*j).m_key == ma.m_key) {
\r
355 case AO_overwrite: {
\r
356 for (ModAssignments::iterator j = mos.begin();
\r
357 j != mos.end(); ++ j)
\r
358 (*j).m_assignMode = (*mai).m_assignMode;
\r
364 // erase redundant modifiers
\r
365 for (ModAssignments::iterator j = mos.begin(); j != mos.end(); ++ j) {
\r
366 ModAssignments::iterator k;
\r
367 for (k = j, ++ k; k != mos.end(); ++ k)
\r
368 if ((*k).m_key == (*j).m_key)
\r
370 if (k != mos.end()) {
\r
378 m_modAssignments[i] = mos;
\r
384 void Keymap::describe(tostream &i_ost, DescribeParam *i_dp) const
\r
386 // Is this keymap already described ?
\r
388 DescribeParam::DescribedKeymap::iterator
\r
389 i = std::find(i_dp->m_dkeymap.begin(), i_dp->m_dkeymap.end(), this);
\r
390 if (i != i_dp->m_dkeymap.end())
\r
392 i_dp->m_dkeymap.push_back(this);
\r
397 i_ost << _T("keymap ") << m_name;
\r
399 case Type_windowAnd:
\r
400 i_ost << _T("window ") << m_name << _T(" ");
\r
401 if (m_windowTitle.str() == _T(".*"))
\r
402 i_ost << _T("/") << m_windowClass.str() << _T("/");
\r
404 i_ost << _T("( /") << m_windowClass.str() << _T("/ && /")
\r
405 << m_windowTitle.str() << _T("/ )");
\r
407 case Type_windowOr:
\r
408 i_ost << _T("window ") << m_name << _T(" ( /")
\r
409 << m_windowClass.str() << _T("/ || /") << m_windowTitle.str()
\r
413 if (m_parentKeymap)
\r
414 i_ost << _T(" : ") << m_parentKeymap->m_name;
\r
415 i_ost << _T(" = ") << *m_defaultKeySeq << std::endl;
\r
417 // describe modifiers
\r
418 if (i_dp->m_doesDescribeModifiers) {
\r
419 for (int t = Modifier::Type_begin; t != Modifier::Type_end; ++ t) {
\r
420 Modifier::Type type = static_cast<Modifier::Type>(t);
\r
421 const Keymap::ModAssignments &ma = getModAssignments(type);
\r
423 i_ost << _T(" mod ") << type << _T("\t= ");
\r
424 for (Keymap::ModAssignments::const_iterator
\r
425 j = ma.begin(); j != ma.end(); ++ j) {
\r
426 switch (j->m_assignMode) {
\r
427 case Keymap::AM_true:
\r
430 case Keymap::AM_oneShot:
\r
433 case Keymap::AM_oneShotRepeatable:
\r
434 i_ost << _T("!!!");
\r
439 i_ost << *j->m_key << _T(" ");
\r
441 i_ost << std::endl;
\r
444 i_dp->m_doesDescribeModifiers = false;
\r
447 typedef std::vector<KeyAssignment> SortedKeyAssignments;
\r
448 SortedKeyAssignments ska;
\r
449 for (size_t i = 0; i < HASHED_KEY_ASSIGNMENT_SIZE; ++ i) {
\r
450 const KeyAssignments &ka = m_hashedKeyAssignments[i];
\r
451 for (KeyAssignments::const_iterator j = ka.begin(); j != ka.end(); ++ j)
\r
454 std::sort(ska.begin(), ska.end());
\r
455 for (SortedKeyAssignments::iterator i = ska.begin(); i != ska.end(); ++ i) {
\r
456 // Is this key assignment already described ?
\r
457 DescribeParam::DescribedKeys::iterator
\r
458 j = std::find(i_dp->m_dk.begin(), i_dp->m_dk.end(), i->m_modifiedKey);
\r
459 if (j != i_dp->m_dk.end())
\r
462 // check if the key is an event
\r
464 for (e = Event::events; *e; ++ e)
\r
465 if (i->m_modifiedKey.m_key == *e)
\r
468 i_ost << _T(" event ") << *i->m_modifiedKey.m_key;
\r
470 i_ost << _T(" key ") << i->m_modifiedKey;
\r
471 i_ost << _T("\t= ") << *i->m_keySeq << std::endl;
\r
472 i_dp->m_dk.push_back(i->m_modifiedKey);
\r
475 i_ost << std::endl;
\r
477 if (m_parentKeymap)
\r
478 m_parentKeymap->describe(i_ost, i_dp);
\r
481 // set default keySeq and parent keymap if default keySeq has not been set
\r
482 bool Keymap::setIfNotYet(KeySeq *i_keySeq, Keymap *i_parentKeymap)
\r
484 if (m_defaultKeySeq)
\r
486 m_defaultKeySeq = i_keySeq;
\r
487 m_parentKeymap = i_parentKeymap;
\r
492 extern tostream &operator<<(tostream &i_ost, const Keymap *i_keymap)
\r
494 return i_ost << i_keymap->getName();
\r
498 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
508 Keymap *Keymaps::searchByName(const tstringi &i_name)
\r
510 for (KeymapList::iterator
\r
511 i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
\r
512 if ((*i).getName() == i_name)
\r
519 void Keymaps::searchWindow(KeymapPtrList *o_keymapPtrList,
\r
520 const tstringi &i_className,
\r
521 const tstringi &i_titleName)
\r
523 o_keymapPtrList->clear();
\r
524 for (KeymapList::iterator
\r
525 i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
\r
526 if ((*i).doesSameWindow(i_className, i_titleName))
\r
527 o_keymapPtrList->push_back(&(*i));
\r
532 Keymap *Keymaps::add(const Keymap &i_keymap)
\r
534 if (Keymap *k = searchByName(i_keymap.getName()))
\r
536 m_keymapList.push_front(i_keymap);
\r
537 return &m_keymapList.front();
\r
542 void Keymaps::adjustModifier(Keyboard &i_keyboard)
\r
544 for (KeymapList::reverse_iterator i = m_keymapList.rbegin();
\r
545 i != m_keymapList.rend(); ++ i)
\r
546 (*i).adjustModifier(i_keyboard);
\r
550 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
554 // add a named keyseq (name can be empty)
\r
555 KeySeq *KeySeqs::add(const KeySeq &i_keySeq)
\r
557 if (!i_keySeq.getName().empty()) {
\r
558 KeySeq *ks = searchByName(i_keySeq.getName());
\r
560 return &(*ks = i_keySeq);
\r
562 m_keySeqList.push_front(i_keySeq);
\r
563 return &m_keySeqList.front();
\r
568 KeySeq *KeySeqs::searchByName(const tstringi &i_name)
\r
570 for (KeySeqList::iterator
\r
571 i = m_keySeqList.begin(); i != m_keySeqList.end(); ++ i)
\r
572 if ((*i).getName() == i_name)
\r