OSDN Git Service

fix invalid file permission
[yamy/yamy.git] / keyboard.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // setting.cpp
3
4
5 #include "keyboard.h"
6
7 #include <algorithm>
8
9
10 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 // Key
12
13
14 // add a name or an alias of key
15 void Key::addName(const tstringi &i_name)
16 {
17   m_names.push_back(i_name);
18 }
19
20
21 // add a scan code
22 void Key::addScanCode(const ScanCode &i_sc)
23 {
24   ASSERT(m_scanCodesSize < MAX_SCAN_CODES_SIZE);
25   m_scanCodes[m_scanCodesSize ++] = i_sc;
26 }
27
28
29 // initializer
30 Key &Key::initialize()
31 {
32   m_names.clear();
33   m_isPressed = false;
34   m_isPressedOnWin32 = false;
35   m_isPressedByAssign = false;
36   m_scanCodesSize = 0;
37   return *this;
38 }
39
40
41 // equation by name
42 bool Key::operator==(const tstringi &i_name) const
43 {
44   return std::find(m_names.begin(), m_names.end(), i_name) != m_names.end();
45 }
46
47   
48 // is the scan code of this key ?
49 bool Key::isSameScanCode(const Key &i_key) const
50 {
51   if (m_scanCodesSize != i_key.m_scanCodesSize)
52     return false;
53   return isPrefixScanCode(i_key);
54 }
55
56
57 // is the key's scan code the prefix of this key's scan code ?
58 bool Key::isPrefixScanCode(const Key &i_key) const
59 {
60   for (size_t i = 0; i < i_key.m_scanCodesSize; ++ i)
61     if (m_scanCodes[i] != i_key.m_scanCodes[i])
62       return false;
63   return true;
64 }
65
66
67 // stream output
68 tostream &operator<<(tostream &i_ost, const Key &i_mk)
69 {
70   return i_ost << i_mk.getName();
71 }
72
73
74 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
75 // Modifier
76
77
78 Modifier::Modifier()
79   : m_modifiers(0),
80     m_dontcares(0)
81 {
82   ASSERT(Type_end <= (sizeof(MODIFIERS) * 8));
83   static const Type defaultDontCare[] =
84   {
85     Type_Up, Type_Down, Type_Repeat,
86     Type_ImeLock, Type_ImeComp, Type_NumLock, Type_CapsLock, Type_ScrollLock,
87         Type_KanaLock,
88     Type_Maximized, Type_Minimized, Type_MdiMaximized, Type_MdiMinimized,
89     Type_Touchpad, Type_TouchpadSticky,
90     Type_Lock0, Type_Lock1, Type_Lock2, Type_Lock3, Type_Lock4,
91     Type_Lock5, Type_Lock6, Type_Lock7, Type_Lock8, Type_Lock9,
92   };
93   for (size_t i = 0; i < NUMBER_OF(defaultDontCare); ++ i)
94     dontcare(defaultDontCare[i]);
95 }
96
97
98 // add m's modifiers where this dontcare
99 void Modifier::add(const Modifier &i_m)
100 {
101   for (int i = 0; i < Type_end; ++ i)
102   {
103     if (isDontcare(static_cast<Modifier::Type>(i)))
104       if (!i_m.isDontcare(static_cast<Modifier::Type>(i)))
105         if (i_m.isPressed(static_cast<Modifier::Type>(i)))
106           press(static_cast<Modifier::Type>(i));
107         else
108           release(static_cast<Modifier::Type>(i));
109   }
110 }
111
112 // stream output
113 tostream &operator<<(tostream &i_ost, const Modifier &i_m)
114 {
115   struct Mods
116   {
117     Modifier::Type m_mt;
118     const _TCHAR *m_symbol;
119   };
120   
121   const static Mods mods[] =
122   {
123     { Modifier::Type_Up, _T("U-") }, { Modifier::Type_Down, _T("D-") },
124     { Modifier::Type_Shift, _T("S-") }, { Modifier::Type_Alt, _T("A-") },
125     { Modifier::Type_Control, _T("C-") }, { Modifier::Type_Windows, _T("W-") },
126     { Modifier::Type_Repeat, _T("R-") },
127     { Modifier::Type_ImeLock, _T("IL-") },
128     { Modifier::Type_ImeComp, _T("IC-") },
129     { Modifier::Type_ImeComp, _T("I-") },
130     { Modifier::Type_NumLock, _T("NL-") },
131     { Modifier::Type_CapsLock, _T("CL-") },
132     { Modifier::Type_ScrollLock, _T("SL-") },
133     { Modifier::Type_KanaLock, _T("KL-") },
134     { Modifier::Type_Maximized, _T("MAX-") },
135     { Modifier::Type_Minimized, _T("MIN-") },
136     { Modifier::Type_MdiMaximized, _T("MMAX-") },
137     { Modifier::Type_MdiMinimized, _T("MMIN-") },
138     { Modifier::Type_Touchpad, _T("T-") },
139     { Modifier::Type_TouchpadSticky, _T("TS-") },
140     { Modifier::Type_Mod0, _T("M0-") }, { Modifier::Type_Mod1, _T("M1-") },
141     { Modifier::Type_Mod2, _T("M2-") }, { Modifier::Type_Mod3, _T("M3-") },
142     { Modifier::Type_Mod4, _T("M4-") }, { Modifier::Type_Mod5, _T("M5-") },
143     { Modifier::Type_Mod6, _T("M6-") }, { Modifier::Type_Mod7, _T("M7-") },
144     { Modifier::Type_Mod8, _T("M8-") }, { Modifier::Type_Mod9, _T("M9-") },
145     { Modifier::Type_Lock0, _T("L0-") }, { Modifier::Type_Lock1, _T("L1-") },
146     { Modifier::Type_Lock2, _T("L2-") }, { Modifier::Type_Lock3, _T("L3-") },
147     { Modifier::Type_Lock4, _T("L4-") }, { Modifier::Type_Lock5, _T("L5-") },
148     { Modifier::Type_Lock6, _T("L6-") }, { Modifier::Type_Lock7, _T("L7-") },
149     { Modifier::Type_Lock8, _T("L8-") }, { Modifier::Type_Lock9, _T("L9-") },
150   };
151
152   for (size_t i = 0; i < NUMBER_OF(mods); ++ i)
153     if (!i_m.isDontcare(mods[i].m_mt) && i_m.isPressed(mods[i].m_mt))
154       i_ost << mods[i].m_symbol;
155 #if 0
156     else if (!i_m.isDontcare(mods[i].m_mt) && i_m.isPressed(mods[i].m_mt))
157       i_ost << _T("~") << mods[i].m_symbol;
158     else
159       i_ost << _T("*") << mods[i].m_symbol;
160 #endif
161
162   return i_ost;
163 }
164
165
166 /// stream output
167 tostream &operator<<(tostream &i_ost, Modifier::Type i_type)
168 {
169   const _TCHAR *modNames[] =
170   {
171     _T("Shift"), 
172     _T("Alt"), 
173     _T("Control"), 
174     _T("Windows"), 
175     _T("Up"), 
176     _T("Down"), 
177     _T("Repeat"), 
178     _T("ImeLock"), 
179     _T("ImeComp"), 
180     _T("NumLock"), 
181     _T("CapsLock"), 
182     _T("ScrollLock"), 
183     _T("KanaLock"), 
184     _T("Maximized"), 
185     _T("Minimized"), 
186     _T("MdiMaximized"), 
187     _T("MdiMinimized"), 
188     _T("Touchpad"), 
189     _T("TouchpadSticky"), 
190     _T("Mod0"), 
191     _T("Mod1"), 
192     _T("Mod2"), 
193     _T("Mod3"), 
194     _T("Mod4"), 
195     _T("Mod5"), 
196     _T("Mod6"), 
197     _T("Mod7"), 
198     _T("Mod8"), 
199     _T("Mod9"), 
200     _T("Lock0"), 
201     _T("Lock1"), 
202     _T("Lock2"), 
203     _T("Lock3"), 
204     _T("Lock4"), 
205     _T("Lock5"), 
206     _T("Lock6"), 
207     _T("Lock7"), 
208     _T("Lock8"), 
209     _T("Lock9"), 
210   };
211
212   int i = static_cast<int>(i_type);
213   if (0 <= i && i < NUMBER_OF(modNames))
214     i_ost << modNames[i];
215   
216   return i_ost;
217 }
218
219
220 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221 // ModifiedKey
222
223
224 // stream output
225 tostream &operator<<(tostream &i_ost, const ModifiedKey &i_mk)
226 {
227   if (i_mk.m_key)
228     i_ost << i_mk.m_modifier << *i_mk.m_key;
229   return i_ost;
230 }
231
232
233 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234 // Keyboard::KeyIterator
235
236
237 Keyboard::KeyIterator::KeyIterator(Keys *i_hashedKeys, size_t i_hashedKeysSize)
238   : m_hashedKeys(i_hashedKeys),
239     m_hashedKeysSize(i_hashedKeysSize),
240     m_i((*m_hashedKeys).begin())
241 {
242   if ((*m_hashedKeys).empty())
243   {
244     do
245     {
246       -- m_hashedKeysSize;
247       ++ m_hashedKeys;
248     } while (0 < m_hashedKeysSize && (*m_hashedKeys).empty());
249     if (0 < m_hashedKeysSize)
250       m_i = (*m_hashedKeys).begin();
251   }
252 }
253
254
255 void Keyboard::KeyIterator::next()
256 {
257   if (m_hashedKeysSize == 0)
258     return;
259   ++ m_i;
260   if (m_i == (*m_hashedKeys).end())
261   {
262     do
263     {
264       -- m_hashedKeysSize;
265       ++ m_hashedKeys;
266     } while (0 < m_hashedKeysSize && (*m_hashedKeys).empty());
267     if (0 < m_hashedKeysSize)
268       m_i = (*m_hashedKeys).begin();
269   }
270 }
271
272
273 Key *Keyboard::KeyIterator::operator *()
274 {
275   if (m_hashedKeysSize == 0)
276     return NULL;
277   return &*m_i;
278 }
279
280
281 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282 // Keyboard
283
284
285 Keyboard::Keys &Keyboard::getKeys(const Key &i_key)
286 {
287   ASSERT(1 <= i_key.getScanCodesSize());
288   return m_hashedKeys[i_key.getScanCodes()->m_scan % HASHED_KEYS_SIZE];
289 }
290
291
292 // add a key
293 void Keyboard::addKey(const Key &i_key)
294 {
295   getKeys(i_key).push_front(i_key);
296 }
297
298
299 // add a key name alias
300 void Keyboard::addAlias(const tstringi &i_aliasName, Key *i_key)
301 {
302   m_aliases.insert(Aliases::value_type(i_aliasName, i_key));
303 }
304
305 // add substitute
306 void Keyboard::addSubstitute(const ModifiedKey &i_mkeyFrom,
307                              const ModifiedKey &i_mkeyTo)
308 {
309   m_substitutes.push_front(Substitute(i_mkeyFrom, i_mkeyTo));
310 }
311
312
313 // add a modifier key
314 void Keyboard::addModifier(Modifier::Type i_mt, Key *i_key)
315 {
316   ASSERT((int)i_mt < (int)Modifier::Type_BASIC);
317   if (std::find(m_mods[i_mt].begin(), m_mods[i_mt].end(), i_key)
318       != m_mods[i_mt].end())
319     return; // already added
320   m_mods[i_mt].push_back(i_key);
321 }
322
323
324 // search a key
325 Key *Keyboard::searchKey(const Key &i_key)
326 {
327   Keys &keys = getKeys(i_key);
328   for (Keys::iterator i = keys.begin(); i != keys.end(); ++ i)
329     if ((*i).isSameScanCode(i_key))
330       return &*i;
331   return NULL;
332 }
333
334
335 // search a key (of which the key's scan code is the prefix)
336 Key *Keyboard::searchPrefixKey(const Key &i_key)
337 {
338   Keys &keys = getKeys(i_key);
339   for (Keys::iterator i = keys.begin(); i != keys.end(); ++ i)
340     if ((*i).isPrefixScanCode(i_key))
341       return &*i;
342   return NULL;
343 }
344
345   
346 // search a key by name
347 Key *Keyboard::searchKey(const tstringi &i_name)
348 {
349   Aliases::iterator i = m_aliases.find(i_name);
350   if (i != m_aliases.end())
351     return (*i).second;
352   return searchKeyByNonAliasName(i_name);
353 }
354
355
356 // search a key by non-alias name
357 Key *Keyboard::searchKeyByNonAliasName(const tstringi &i_name)
358 {
359   for (int j = 0; j < HASHED_KEYS_SIZE; ++ j)
360   {
361     Keys &keys = m_hashedKeys[j];
362     Keys::iterator i = std::find(keys.begin(), keys.end(), i_name);
363     if (i != keys.end())
364       return &*i;
365   }
366   return NULL;
367 }
368
369 /// search a substitute
370 ModifiedKey Keyboard::searchSubstitute(const ModifiedKey &i_mkey)
371 {
372   for (Substitutes::const_iterator
373          i = m_substitutes.begin(); i != m_substitutes.end(); ++ i)
374     if (i->m_mkeyFrom.m_key == i_mkey.m_key &&
375         i->m_mkeyFrom.m_modifier.doesMatch(i_mkey.m_modifier))
376       return i->m_mkeyTo;
377   return ModifiedKey();                         // not found (.m_mkey is NULL)
378 }