OSDN Git Service

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