OSDN Git Service

47d7a29c7ef8ee199126ee0eeb22548bcb311648
[yamy/yamy.git] / keymap.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // setting.cpp
3
4
5 #include "keymap.h"
6 #include "errormessage.h"
7 #include "stringtool.h"
8 #include "setting.h"
9 #include <algorithm>
10
11
12 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 // Action
14
15 //
16 tostream &operator<<(tostream &i_ost, const Action &i_action)
17 {
18   return i_action.output(i_ost);
19 }
20
21
22 //
23 ActionKey::ActionKey(const ModifiedKey &i_mk)
24   : m_modifiedKey(i_mk)
25 {
26 }
27
28 //
29 Action::Type ActionKey::getType() const
30 {
31   return Type_key;
32 }
33
34 // create clone
35 Action *ActionKey::clone() const
36 {
37   return new ActionKey(m_modifiedKey);
38 }
39
40 // stream output
41 tostream &ActionKey::output(tostream &i_ost) const
42 {
43   return i_ost << m_modifiedKey;
44 }
45
46 //
47 ActionKeySeq::ActionKeySeq(KeySeq *i_keySeq)
48   : m_keySeq(i_keySeq)
49 {
50 }
51
52 //
53 Action::Type ActionKeySeq::getType() const
54 {
55   return Type_keySeq;
56 }
57
58 // create clone
59 Action *ActionKeySeq::clone() const
60 {
61   return new ActionKeySeq(m_keySeq);
62 }
63
64 // stream output
65 tostream &ActionKeySeq::output(tostream &i_ost) const
66 {
67   return i_ost << _T("$") << m_keySeq->getName();
68 }
69
70 //
71 ActionFunction::ActionFunction(FunctionData *i_functionData,
72                                Modifier i_modifier)
73   : m_functionData(i_functionData),
74     m_modifier(i_modifier)
75 {
76 }
77
78 //
79 ActionFunction::~ActionFunction()
80 {
81   delete m_functionData;
82 }
83
84 //
85 Action::Type ActionFunction::getType() const
86 {
87   return Type_function;
88 }
89
90 // create clone
91 Action *ActionFunction::clone() const
92 {
93   return new ActionFunction(m_functionData->clone(), m_modifier);
94 }
95
96 // stream output
97 tostream &ActionFunction::output(tostream &i_ost) const
98 {
99   return i_ost << m_modifier << m_functionData;
100 }
101
102
103 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
104 // KeySeq
105
106
107 void KeySeq::copy()
108 {
109   for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
110     (*i) = (*i)->clone();
111 }
112
113
114 void KeySeq::clear()
115 {
116   for (Actions::iterator i = m_actions.begin(); i != m_actions.end(); ++ i)
117     delete (*i);
118 }
119
120
121 KeySeq::KeySeq(const tstringi &i_name)
122   : m_name(i_name),
123     m_mode(Modifier::Type_KEYSEQ)
124 {
125 }
126
127
128 KeySeq::KeySeq(const KeySeq &i_ks)
129   : m_actions(i_ks.m_actions),
130     m_name(i_ks.m_name),
131     m_mode(i_ks.m_mode)
132 {
133   copy();
134 }
135
136
137 KeySeq::~KeySeq()
138 {
139   clear();
140 }
141
142
143 KeySeq &KeySeq::operator=(const KeySeq &i_ks)
144 {
145   if (this != &i_ks)
146   {
147     clear();
148     m_actions = i_ks.m_actions;
149     m_mode = i_ks.m_mode;
150     copy();
151   }
152   return *this;
153 }
154
155
156 KeySeq &KeySeq::add(const Action &i_action)
157 {
158   m_actions.push_back(i_action.clone());
159   return *this;
160 }
161
162
163 /// get the first modified key of this key sequence
164 ModifiedKey KeySeq::getFirstModifiedKey() const
165 {
166   if (0 < m_actions.size())
167   {
168     const Action *a = m_actions.front();
169     switch (a->getType())
170     {
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();
176       default:
177         break;
178     }
179   }
180   return ModifiedKey();                         // failed
181 }
182
183
184 // stream output
185 tostream &operator<<(tostream &i_ost, const KeySeq &i_ks)
186 {
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(" ");
190   return i_ost;
191 }
192
193
194 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195 // Keymap
196
197
198 Keymap::KeyAssignments &Keymap::getKeyAssignments(const ModifiedKey &i_mk)
199 {
200   ASSERT(1 <= i_mk.m_key->getScanCodesSize());
201   return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
202                                HASHED_KEY_ASSIGNMENT_SIZE];
203 }
204
205 const Keymap::KeyAssignments &
206 Keymap::getKeyAssignments(const ModifiedKey &i_mk) const
207 {
208   ASSERT(1 <= i_mk.m_key->getScanCodesSize());
209   return m_hashedKeyAssignments[i_mk.m_key->getScanCodes()->m_scan %
210                                HASHED_KEY_ASSIGNMENT_SIZE];
211 }
212
213
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)
220   : m_type(i_type),
221     m_name(i_name),
222     m_defaultKeySeq(i_defaultKeySeq),
223     m_parentKeymap(i_parentKeymap),
224     m_windowClass(_T(".*")),
225     m_windowTitle(_T(".*"))
226 {
227   if (i_type == Type_windowAnd || i_type == Type_windowOr)
228     try
229     {
230       tregex::flag_type f = (tregex::normal | 
231                              tregex::icase);
232       if (!i_windowClass.empty())
233         m_windowClass.assign(i_windowClass, f);
234       if (!i_windowTitle.empty())
235         m_windowTitle.assign(i_windowTitle, f);
236     }
237     catch (boost::bad_expression &i_e)
238     {
239       throw ErrorMessage() << i_e.what();
240     }
241 }
242
243
244 // add a key assignment;
245 void Keymap::addAssignment(const ModifiedKey &i_mk, KeySeq *i_keySeq)
246 {
247   KeyAssignments &ka = getKeyAssignments(i_mk);
248   for (KeyAssignments::iterator i = ka.begin(); i != ka.end(); ++ i)
249     if ((*i).m_modifiedKey == i_mk)
250     {
251       (*i).m_keySeq = i_keySeq;
252       return;
253     }
254   ka.push_front(KeyAssignment(i_mk, i_keySeq));
255 }
256
257
258 // add modifier
259 void Keymap::addModifier(Modifier::Type i_mt, AssignOperator i_ao,
260                          AssignMode i_am, Key *i_key)
261 {
262   if (i_ao == AO_new)
263     m_modAssignments[i_mt].clear();
264   else
265   {
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)
269       {
270         (*i).m_assignOperator = i_ao;
271         (*i).m_assignMode = i_am;
272         return;
273       }
274   }
275   ModAssignment ma;
276   ma.m_assignOperator = i_ao;
277   ma.m_assignMode = i_am;
278   ma.m_key = i_key;
279   m_modAssignments[i_mt].push_back(ma);
280 }
281
282   
283 // search
284 const Keymap::KeyAssignment *
285 Keymap::searchAssignment(const ModifiedKey &i_mk) const
286 {
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))
291       return &(*i);
292   return NULL;
293 }
294
295
296 // does same window
297 bool Keymap::doesSameWindow(const tstringi i_className,
298                             const tstringi &i_titleName)
299 {
300   if (m_type == Type_keymap)
301     return false;
302
303   tsmatch what;
304   if (boost::regex_search(i_className, what, m_windowClass))
305   {
306     if (m_type == Type_windowAnd)
307       return boost::regex_search(i_titleName, what, m_windowTitle);
308     else // type == Type_windowOr
309       return true;
310   }
311   else
312   {
313     if (m_type == Type_windowAnd)
314       return false;
315     else // type == Type_windowOr
316       return boost::regex_search(i_titleName, what, m_windowTitle);
317   }
318 }
319
320
321 // adjust modifier
322 void Keymap::adjustModifier(Keyboard &i_keyboard)
323 {
324   for (size_t i = 0; i < NUMBER_OF(m_modAssignments); ++ i)
325   {
326     ModAssignments mos;
327     if (m_parentKeymap)
328       mos = m_parentKeymap->m_modAssignments[i];
329     else
330     {
331       // set default modifiers
332       if (i < Modifier::Type_BASIC)
333       {
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)
337         {
338           ModAssignment ma;
339           ma.m_assignOperator = AO_add;
340           ma.m_assignMode = AM_normal;
341           ma.m_key = *j;
342           mos.push_back(ma);
343         }
344       }
345     }
346     
347     // mod adjust
348     for (ModAssignments::iterator mai = m_modAssignments[i].begin();
349          mai != m_modAssignments[i].end(); ++ mai)
350     {
351       ModAssignment ma = *mai;
352       ma.m_assignOperator = AO_new;
353       switch ((*mai).m_assignOperator)
354       {
355         case AO_new:
356         {
357           mos.clear();
358           mos.push_back(ma);
359           break;
360         }
361         case AO_add:
362         {
363           mos.push_back(ma);
364           break;
365         }
366         case AO_sub:
367         {
368           for (ModAssignments::iterator j = mos.begin();
369                j != mos.end(); ++ j)
370             if ((*j).m_key == ma.m_key)
371             {
372               mos.erase(j);
373               break;
374             }
375           break;
376         }
377         case AO_overwrite:
378         {
379           for (ModAssignments::iterator j = mos.begin();
380                j != mos.end(); ++ j)
381             (*j).m_assignMode = (*mai).m_assignMode;
382           break;
383         }
384       }
385     }
386
387     // erase redundant modifiers
388     for (ModAssignments::iterator j = mos.begin(); j != mos.end(); ++ j)
389     {
390       ModAssignments::iterator k;
391       for (k = j, ++ k; k != mos.end(); ++ k)
392         if ((*k).m_key == (*j).m_key)
393           break;
394       if (k != mos.end())
395       {
396         k = j;
397         ++ j;
398         mos.erase(k);
399         break;
400       }
401     }
402     
403     m_modAssignments[i] = mos;
404   }
405 }
406
407
408 // describe
409 void Keymap::describe(tostream &i_ost, DescribeParam *i_dp) const
410 {
411   // Is this keymap already described ?
412   {
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())
416       return;                                   // yes!
417     i_dp->m_dkeymap.push_back(this);
418   }
419
420   switch (m_type)
421   {
422     case Type_keymap:
423       i_ost << _T("keymap ") << m_name;
424       break;
425     case Type_windowAnd:
426       i_ost << _T("window ") << m_name << _T(" ");
427       if (m_windowTitle.str() == _T(".*"))
428         i_ost << _T("/") << m_windowClass.str() << _T("/");
429       else
430         i_ost << _T("( /") << m_windowClass.str() << _T("/ && /")
431               << m_windowTitle.str() << _T("/ )");
432       break;
433     case Type_windowOr:
434       i_ost << _T("window ") << m_name << _T(" ( /")
435             << m_windowClass.str() << _T("/ || /") << m_windowTitle.str()
436             << _T("/ )");
437       break;
438   }
439   if (m_parentKeymap)
440     i_ost << _T(" : ") << m_parentKeymap->m_name;
441   i_ost << _T(" = ") << *m_defaultKeySeq << std::endl;
442
443   // describe modifiers
444   if (i_dp->m_doesDescribeModifiers)
445   {
446     for (int t = Modifier::Type_begin; t != Modifier::Type_end; ++ t)
447     {
448       Modifier::Type type = static_cast<Modifier::Type>(t);
449       const Keymap::ModAssignments &ma = getModAssignments(type);
450       if (ma.size())
451       {
452         i_ost << _T(" mod ") << type << _T("\t= ");
453         for (Keymap::ModAssignments::const_iterator
454                j = ma.begin(); j != ma.end(); ++ j)
455         {
456           switch (j->m_assignMode)
457           {
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;
461             default:
462               break;
463           }
464           i_ost << *j->m_key << _T(" ");
465         }
466         i_ost << std::endl;
467       }
468     }
469     i_dp->m_doesDescribeModifiers = false;
470   }
471   
472   typedef std::vector<KeyAssignment> SortedKeyAssignments;
473   SortedKeyAssignments ska;
474   for (size_t i = 0; i < HASHED_KEY_ASSIGNMENT_SIZE; ++ i)
475   {
476     const KeyAssignments &ka = m_hashedKeyAssignments[i];
477     for (KeyAssignments::const_iterator j = ka.begin(); j != ka.end(); ++ j)
478       ska.push_back(*j);
479   }
480   std::sort(ska.begin(), ska.end());
481   for (SortedKeyAssignments::iterator i = ska.begin(); i != ska.end(); ++ i)
482   {
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())
487       continue;                                 // yes!
488
489     // check if the key is an event
490     Key **e;
491     for (e = Event::events; *e; ++ e)
492       if (i->m_modifiedKey.m_key == *e)
493         break;
494     if (*e)
495       i_ost << _T(" event ") << *i->m_modifiedKey.m_key;
496     else
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);
500   }
501
502   i_ost << std::endl;
503   
504   if (m_parentKeymap)
505     m_parentKeymap->describe(i_ost, i_dp);
506 }
507
508 // set default keySeq and parent keymap if default keySeq has not been set
509 bool Keymap::setIfNotYet(KeySeq *i_keySeq, Keymap *i_parentKeymap)
510 {
511   if (m_defaultKeySeq)
512     return false;
513   m_defaultKeySeq = i_keySeq;
514   m_parentKeymap = i_parentKeymap;
515   return true;
516 }
517
518 // stream output
519 extern tostream &operator<<(tostream &i_ost, const Keymap *i_keymap)
520 {
521   return i_ost << i_keymap->getName();
522 }
523
524
525 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
526 // Keymaps
527
528
529 Keymaps::Keymaps()
530 {
531 }
532
533
534 // search by name
535 Keymap *Keymaps::searchByName(const tstringi &i_name)
536 {
537   for (KeymapList::iterator
538          i = m_keymapList.begin(); i != m_keymapList.end(); ++ i)
539     if ((*i).getName() == i_name)
540       return &*i;
541   return NULL;
542 }
543
544
545 // search window
546 void Keymaps::searchWindow(KeymapPtrList *o_keymapPtrList,
547                            const tstringi &i_className,
548                            const tstringi &i_titleName)
549 {
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));
555 }
556
557
558 // add keymap
559 Keymap *Keymaps::add(const Keymap &i_keymap)
560 {
561   if (Keymap *k = searchByName(i_keymap.getName()))
562     return k;
563   m_keymapList.push_front(i_keymap);
564   return &m_keymapList.front();
565 }
566
567
568 // adjust modifier
569 void Keymaps::adjustModifier(Keyboard &i_keyboard)
570 {
571   for (KeymapList::reverse_iterator i = m_keymapList.rbegin();
572        i != m_keymapList.rend(); ++ i)
573     (*i).adjustModifier(i_keyboard);
574 }
575
576
577 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
578 // KeySeqs
579
580
581 // add a named keyseq (name can be empty)
582 KeySeq *KeySeqs::add(const KeySeq &i_keySeq)
583 {
584   if (!i_keySeq.getName().empty())
585   {
586     KeySeq *ks = searchByName(i_keySeq.getName());
587     if (ks)
588       return &(*ks = i_keySeq);
589   }
590   m_keySeqList.push_front(i_keySeq);
591   return &m_keySeqList.front();
592 }
593
594
595 // search by name
596 KeySeq *KeySeqs::searchByName(const tstringi &i_name)
597 {
598   for (KeySeqList::iterator
599          i = m_keySeqList.begin(); i != m_keySeqList.end(); ++ i)
600     if ((*i).getName() == i_name)
601       return &(*i);
602   return NULL;
603 }