1 /*
2  * Kuklomenos
3  * Copyright (C) 2008-2009 Martin Bays <mbays@sdf.lonestar.org>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see http://www.gnu.org/licenses/.
17  */
18 
19 #include <config.h>
20 #ifdef HAVE_LIBCURL
21 #define HIGH_SCORE_REPORTING 1
22 #endif
23 
24 #include <string>
25 #include <map>
26 using namespace std;
27 
28 #include "keybindings.h"
29 
30 const command C_FIRST = C_LEFT;
31 const command C_LAST = C_SCREENSHOT;
32 const command C_LASTACTION = C_STARTGAME;
33 const command C_LASTDEBUG = C_WIN;
34 
35 string longCommandNames[] = {
36     "BUG",
37     "Turn left",
38     "Turn right",
39     "Dezoom",
40     "De-aim",
41     "Shoot green",
42     "Shoot yellow",
43     "Shoot red",
44     "Shoot pod",
45     "Pause",
46     "Quit",
47     "Menu",
48     "Menu left",
49     "Menu up",
50     "Menu right",
51     "Menu down",
52     "Start game",
53 #ifdef SOUND
54     "Toggle sound",
55 #endif
56     "Toggle zoom",
57     "Toggle rotate",
58     "Toggle grid",
59     "Decrease anti-aliasing",
60     "Increase anti-aliasing",
61     "Decrease fps",
62     "Increase fps",
63     "Decrease game rate",
64     "Increase game rate",
65     "Reset game rate",
66 #ifdef HIGH_SCORE_REPORTING
67     "Report high score",
68 #endif
69     "Take screenshot",
70     "[DEBUG] Invulnerability",
71     "[DEBUG] Win",
72 };
73 string shortCommandNames[] = {
74     "BUG",
75     "left",
76     "right",
77     "dezoom",
78     "deaim",
79     "shoot1",
80     "shoot2",
81     "shoot3",
82     "shoot4",
83     "pause",
84     "quit",
85     "menu",
86     "menu_left",
87     "menu_up",
88     "menu_right",
89     "menu_down",
90     "start",
91 #ifdef SOUND
92     "sound",
93 #endif
94     "zoom",
95     "rotate",
96     "grid",
97     "decaa",
98     "incaa",
99     "decfps",
100     "incfps",
101     "decrate",
102     "incrate",
103     "resetrate",
104 #ifdef HIGH_SCORE_REPORTING
105     "reporths",
106 #endif
107     "screenshot",
108     "invuln",
109     "win"
110 };
111 
commandOfString(const string & str)112 command commandOfString(const string& str)
113 {
114     for (command c = C_FIRST; c <= C_LASTDEBUG; c = command(c+1))
115 	if (str == shortCommandNames[c])
116 	    return c;
117     return C_NONE;
118 }
119 
isMenuCommand(const command & c)120 bool isMenuCommand(const command& c)
121 {
122     return (c >= C_M_LEFT && c <= C_M_DOWN);
123 }
124 
simpleMod(const SDLMod & in) const125 SDLMod Key::simpleMod(const SDLMod& in) const
126 {
127     return SDLMod(((in & KMOD_SHIFT) ? KMOD_SHIFT : KMOD_NONE) |
128 	    ((in & KMOD_CTRL) ? KMOD_CTRL : KMOD_NONE) |
129 	    (((in & KMOD_ALT) | (in & KMOD_META)) ?
130 	     KMOD_ALT : KMOD_NONE));
131 }
132 
Key(SDL_keysym keysym)133 Key::Key(SDL_keysym keysym)
134 {
135     // care only about shift, ctrl, and alt/meta.
136     sym = keysym.sym;
137     mod = simpleMod(keysym.mod);
138 }
139 
140 struct strcomp {
operator ()strcomp141     bool operator() (const string& str1, const string& str2) const
142     { return (str1.compare(str2) < 0); }
143 };
144 
Key(string keyString)145 Key::Key(string keyString)
146 {
147     static map<string,SDLKey,strcomp> keynameMap;
148     if (keynameMap.size() == 0)
149     {
150 	// initialise keynameMap; big long list of keys taken from
151 	// SDL_keyboard.c (SDL version 1.2.13).
152 	// Sadly we can't just use SDL_GetKeyName itself, as we want to be
153 	// able to run this before initialising video.
154 	keynameMap.insert( pair<string,SDLKey>("backspace",SDLK_BACKSPACE) );
155 	keynameMap.insert( pair<string,SDLKey>("tab",SDLK_TAB) );
156 	keynameMap.insert( pair<string,SDLKey>("clear",SDLK_CLEAR) );
157 	keynameMap.insert( pair<string,SDLKey>("return",SDLK_RETURN) );
158 	keynameMap.insert( pair<string,SDLKey>("pause",SDLK_PAUSE) );
159 	keynameMap.insert( pair<string,SDLKey>("escape",SDLK_ESCAPE) );
160 	keynameMap.insert( pair<string,SDLKey>("space",SDLK_SPACE) );
161 	keynameMap.insert( pair<string,SDLKey>("!",SDLK_EXCLAIM) );
162 	keynameMap.insert( pair<string,SDLKey>("\"",SDLK_QUOTEDBL) );
163 	keynameMap.insert( pair<string,SDLKey>("#",SDLK_HASH) );
164 	keynameMap.insert( pair<string,SDLKey>("$",SDLK_DOLLAR) );
165 	keynameMap.insert( pair<string,SDLKey>("&",SDLK_AMPERSAND) );
166 	keynameMap.insert( pair<string,SDLKey>("'",SDLK_QUOTE) );
167 	keynameMap.insert( pair<string,SDLKey>("(",SDLK_LEFTPAREN) );
168 	keynameMap.insert( pair<string,SDLKey>(")",SDLK_RIGHTPAREN) );
169 	keynameMap.insert( pair<string,SDLKey>("*",SDLK_ASTERISK) );
170 	keynameMap.insert( pair<string,SDLKey>("+",SDLK_PLUS) );
171 	keynameMap.insert( pair<string,SDLKey>(",",SDLK_COMMA) );
172 	keynameMap.insert( pair<string,SDLKey>("-",SDLK_MINUS) );
173 	keynameMap.insert( pair<string,SDLKey>(".",SDLK_PERIOD) );
174 	keynameMap.insert( pair<string,SDLKey>("/",SDLK_SLASH) );
175 	keynameMap.insert( pair<string,SDLKey>("0",SDLK_0) );
176 	keynameMap.insert( pair<string,SDLKey>("1",SDLK_1) );
177 	keynameMap.insert( pair<string,SDLKey>("2",SDLK_2) );
178 	keynameMap.insert( pair<string,SDLKey>("3",SDLK_3) );
179 	keynameMap.insert( pair<string,SDLKey>("4",SDLK_4) );
180 	keynameMap.insert( pair<string,SDLKey>("5",SDLK_5) );
181 	keynameMap.insert( pair<string,SDLKey>("6",SDLK_6) );
182 	keynameMap.insert( pair<string,SDLKey>("7",SDLK_7) );
183 	keynameMap.insert( pair<string,SDLKey>("8",SDLK_8) );
184 	keynameMap.insert( pair<string,SDLKey>("9",SDLK_9) );
185 	keynameMap.insert( pair<string,SDLKey>(":",SDLK_COLON) );
186 	keynameMap.insert( pair<string,SDLKey>(";",SDLK_SEMICOLON) );
187 	keynameMap.insert( pair<string,SDLKey>("<",SDLK_LESS) );
188 	keynameMap.insert( pair<string,SDLKey>("=",SDLK_EQUALS) );
189 	keynameMap.insert( pair<string,SDLKey>(">",SDLK_GREATER) );
190 	keynameMap.insert( pair<string,SDLKey>("?",SDLK_QUESTION) );
191 	keynameMap.insert( pair<string,SDLKey>("@",SDLK_AT) );
192 	keynameMap.insert( pair<string,SDLKey>("[",SDLK_LEFTBRACKET) );
193 	keynameMap.insert( pair<string,SDLKey>("\\",SDLK_BACKSLASH) );
194 	keynameMap.insert( pair<string,SDLKey>("]",SDLK_RIGHTBRACKET) );
195 	keynameMap.insert( pair<string,SDLKey>("^",SDLK_CARET) );
196 	keynameMap.insert( pair<string,SDLKey>("_",SDLK_UNDERSCORE) );
197 	keynameMap.insert( pair<string,SDLKey>("`",SDLK_BACKQUOTE) );
198 	keynameMap.insert( pair<string,SDLKey>("a",SDLK_a) );
199 	keynameMap.insert( pair<string,SDLKey>("b",SDLK_b) );
200 	keynameMap.insert( pair<string,SDLKey>("c",SDLK_c) );
201 	keynameMap.insert( pair<string,SDLKey>("d",SDLK_d) );
202 	keynameMap.insert( pair<string,SDLKey>("e",SDLK_e) );
203 	keynameMap.insert( pair<string,SDLKey>("f",SDLK_f) );
204 	keynameMap.insert( pair<string,SDLKey>("g",SDLK_g) );
205 	keynameMap.insert( pair<string,SDLKey>("h",SDLK_h) );
206 	keynameMap.insert( pair<string,SDLKey>("i",SDLK_i) );
207 	keynameMap.insert( pair<string,SDLKey>("j",SDLK_j) );
208 	keynameMap.insert( pair<string,SDLKey>("k",SDLK_k) );
209 	keynameMap.insert( pair<string,SDLKey>("l",SDLK_l) );
210 	keynameMap.insert( pair<string,SDLKey>("m",SDLK_m) );
211 	keynameMap.insert( pair<string,SDLKey>("n",SDLK_n) );
212 	keynameMap.insert( pair<string,SDLKey>("o",SDLK_o) );
213 	keynameMap.insert( pair<string,SDLKey>("p",SDLK_p) );
214 	keynameMap.insert( pair<string,SDLKey>("q",SDLK_q) );
215 	keynameMap.insert( pair<string,SDLKey>("r",SDLK_r) );
216 	keynameMap.insert( pair<string,SDLKey>("s",SDLK_s) );
217 	keynameMap.insert( pair<string,SDLKey>("t",SDLK_t) );
218 	keynameMap.insert( pair<string,SDLKey>("u",SDLK_u) );
219 	keynameMap.insert( pair<string,SDLKey>("v",SDLK_v) );
220 	keynameMap.insert( pair<string,SDLKey>("w",SDLK_w) );
221 	keynameMap.insert( pair<string,SDLKey>("x",SDLK_x) );
222 	keynameMap.insert( pair<string,SDLKey>("y",SDLK_y) );
223 	keynameMap.insert( pair<string,SDLKey>("z",SDLK_z) );
224 	keynameMap.insert( pair<string,SDLKey>("delete",SDLK_DELETE) );
225 
226 	keynameMap.insert( pair<string,SDLKey>("world 0",SDLK_WORLD_0) );
227 	keynameMap.insert( pair<string,SDLKey>("world 1",SDLK_WORLD_1) );
228 	keynameMap.insert( pair<string,SDLKey>("world 2",SDLK_WORLD_2) );
229 	keynameMap.insert( pair<string,SDLKey>("world 3",SDLK_WORLD_3) );
230 	keynameMap.insert( pair<string,SDLKey>("world 4",SDLK_WORLD_4) );
231 	keynameMap.insert( pair<string,SDLKey>("world 5",SDLK_WORLD_5) );
232 	keynameMap.insert( pair<string,SDLKey>("world 6",SDLK_WORLD_6) );
233 	keynameMap.insert( pair<string,SDLKey>("world 7",SDLK_WORLD_7) );
234 	keynameMap.insert( pair<string,SDLKey>("world 8",SDLK_WORLD_8) );
235 	keynameMap.insert( pair<string,SDLKey>("world 9",SDLK_WORLD_9) );
236 	keynameMap.insert( pair<string,SDLKey>("world 10",SDLK_WORLD_10) );
237 	keynameMap.insert( pair<string,SDLKey>("world 11",SDLK_WORLD_11) );
238 	keynameMap.insert( pair<string,SDLKey>("world 12",SDLK_WORLD_12) );
239 	keynameMap.insert( pair<string,SDLKey>("world 13",SDLK_WORLD_13) );
240 	keynameMap.insert( pair<string,SDLKey>("world 14",SDLK_WORLD_14) );
241 	keynameMap.insert( pair<string,SDLKey>("world 15",SDLK_WORLD_15) );
242 	keynameMap.insert( pair<string,SDLKey>("world 16",SDLK_WORLD_16) );
243 	keynameMap.insert( pair<string,SDLKey>("world 17",SDLK_WORLD_17) );
244 	keynameMap.insert( pair<string,SDLKey>("world 18",SDLK_WORLD_18) );
245 	keynameMap.insert( pair<string,SDLKey>("world 19",SDLK_WORLD_19) );
246 	keynameMap.insert( pair<string,SDLKey>("world 20",SDLK_WORLD_20) );
247 	keynameMap.insert( pair<string,SDLKey>("world 21",SDLK_WORLD_21) );
248 	keynameMap.insert( pair<string,SDLKey>("world 22",SDLK_WORLD_22) );
249 	keynameMap.insert( pair<string,SDLKey>("world 23",SDLK_WORLD_23) );
250 	keynameMap.insert( pair<string,SDLKey>("world 24",SDLK_WORLD_24) );
251 	keynameMap.insert( pair<string,SDLKey>("world 25",SDLK_WORLD_25) );
252 	keynameMap.insert( pair<string,SDLKey>("world 26",SDLK_WORLD_26) );
253 	keynameMap.insert( pair<string,SDLKey>("world 27",SDLK_WORLD_27) );
254 	keynameMap.insert( pair<string,SDLKey>("world 28",SDLK_WORLD_28) );
255 	keynameMap.insert( pair<string,SDLKey>("world 29",SDLK_WORLD_29) );
256 	keynameMap.insert( pair<string,SDLKey>("world 30",SDLK_WORLD_30) );
257 	keynameMap.insert( pair<string,SDLKey>("world 31",SDLK_WORLD_31) );
258 	keynameMap.insert( pair<string,SDLKey>("world 32",SDLK_WORLD_32) );
259 	keynameMap.insert( pair<string,SDLKey>("world 33",SDLK_WORLD_33) );
260 	keynameMap.insert( pair<string,SDLKey>("world 34",SDLK_WORLD_34) );
261 	keynameMap.insert( pair<string,SDLKey>("world 35",SDLK_WORLD_35) );
262 	keynameMap.insert( pair<string,SDLKey>("world 36",SDLK_WORLD_36) );
263 	keynameMap.insert( pair<string,SDLKey>("world 37",SDLK_WORLD_37) );
264 	keynameMap.insert( pair<string,SDLKey>("world 38",SDLK_WORLD_38) );
265 	keynameMap.insert( pair<string,SDLKey>("world 39",SDLK_WORLD_39) );
266 	keynameMap.insert( pair<string,SDLKey>("world 40",SDLK_WORLD_40) );
267 	keynameMap.insert( pair<string,SDLKey>("world 41",SDLK_WORLD_41) );
268 	keynameMap.insert( pair<string,SDLKey>("world 42",SDLK_WORLD_42) );
269 	keynameMap.insert( pair<string,SDLKey>("world 43",SDLK_WORLD_43) );
270 	keynameMap.insert( pair<string,SDLKey>("world 44",SDLK_WORLD_44) );
271 	keynameMap.insert( pair<string,SDLKey>("world 45",SDLK_WORLD_45) );
272 	keynameMap.insert( pair<string,SDLKey>("world 46",SDLK_WORLD_46) );
273 	keynameMap.insert( pair<string,SDLKey>("world 47",SDLK_WORLD_47) );
274 	keynameMap.insert( pair<string,SDLKey>("world 48",SDLK_WORLD_48) );
275 	keynameMap.insert( pair<string,SDLKey>("world 49",SDLK_WORLD_49) );
276 	keynameMap.insert( pair<string,SDLKey>("world 50",SDLK_WORLD_50) );
277 	keynameMap.insert( pair<string,SDLKey>("world 51",SDLK_WORLD_51) );
278 	keynameMap.insert( pair<string,SDLKey>("world 52",SDLK_WORLD_52) );
279 	keynameMap.insert( pair<string,SDLKey>("world 53",SDLK_WORLD_53) );
280 	keynameMap.insert( pair<string,SDLKey>("world 54",SDLK_WORLD_54) );
281 	keynameMap.insert( pair<string,SDLKey>("world 55",SDLK_WORLD_55) );
282 	keynameMap.insert( pair<string,SDLKey>("world 56",SDLK_WORLD_56) );
283 	keynameMap.insert( pair<string,SDLKey>("world 57",SDLK_WORLD_57) );
284 	keynameMap.insert( pair<string,SDLKey>("world 58",SDLK_WORLD_58) );
285 	keynameMap.insert( pair<string,SDLKey>("world 59",SDLK_WORLD_59) );
286 	keynameMap.insert( pair<string,SDLKey>("world 60",SDLK_WORLD_60) );
287 	keynameMap.insert( pair<string,SDLKey>("world 61",SDLK_WORLD_61) );
288 	keynameMap.insert( pair<string,SDLKey>("world 62",SDLK_WORLD_62) );
289 	keynameMap.insert( pair<string,SDLKey>("world 63",SDLK_WORLD_63) );
290 	keynameMap.insert( pair<string,SDLKey>("world 64",SDLK_WORLD_64) );
291 	keynameMap.insert( pair<string,SDLKey>("world 65",SDLK_WORLD_65) );
292 	keynameMap.insert( pair<string,SDLKey>("world 66",SDLK_WORLD_66) );
293 	keynameMap.insert( pair<string,SDLKey>("world 67",SDLK_WORLD_67) );
294 	keynameMap.insert( pair<string,SDLKey>("world 68",SDLK_WORLD_68) );
295 	keynameMap.insert( pair<string,SDLKey>("world 69",SDLK_WORLD_69) );
296 	keynameMap.insert( pair<string,SDLKey>("world 70",SDLK_WORLD_70) );
297 	keynameMap.insert( pair<string,SDLKey>("world 71",SDLK_WORLD_71) );
298 	keynameMap.insert( pair<string,SDLKey>("world 72",SDLK_WORLD_72) );
299 	keynameMap.insert( pair<string,SDLKey>("world 73",SDLK_WORLD_73) );
300 	keynameMap.insert( pair<string,SDLKey>("world 74",SDLK_WORLD_74) );
301 	keynameMap.insert( pair<string,SDLKey>("world 75",SDLK_WORLD_75) );
302 	keynameMap.insert( pair<string,SDLKey>("world 76",SDLK_WORLD_76) );
303 	keynameMap.insert( pair<string,SDLKey>("world 77",SDLK_WORLD_77) );
304 	keynameMap.insert( pair<string,SDLKey>("world 78",SDLK_WORLD_78) );
305 	keynameMap.insert( pair<string,SDLKey>("world 79",SDLK_WORLD_79) );
306 	keynameMap.insert( pair<string,SDLKey>("world 80",SDLK_WORLD_80) );
307 	keynameMap.insert( pair<string,SDLKey>("world 81",SDLK_WORLD_81) );
308 	keynameMap.insert( pair<string,SDLKey>("world 82",SDLK_WORLD_82) );
309 	keynameMap.insert( pair<string,SDLKey>("world 83",SDLK_WORLD_83) );
310 	keynameMap.insert( pair<string,SDLKey>("world 84",SDLK_WORLD_84) );
311 	keynameMap.insert( pair<string,SDLKey>("world 85",SDLK_WORLD_85) );
312 	keynameMap.insert( pair<string,SDLKey>("world 86",SDLK_WORLD_86) );
313 	keynameMap.insert( pair<string,SDLKey>("world 87",SDLK_WORLD_87) );
314 	keynameMap.insert( pair<string,SDLKey>("world 88",SDLK_WORLD_88) );
315 	keynameMap.insert( pair<string,SDLKey>("world 89",SDLK_WORLD_89) );
316 	keynameMap.insert( pair<string,SDLKey>("world 90",SDLK_WORLD_90) );
317 	keynameMap.insert( pair<string,SDLKey>("world 91",SDLK_WORLD_91) );
318 	keynameMap.insert( pair<string,SDLKey>("world 92",SDLK_WORLD_92) );
319 	keynameMap.insert( pair<string,SDLKey>("world 93",SDLK_WORLD_93) );
320 	keynameMap.insert( pair<string,SDLKey>("world 94",SDLK_WORLD_94) );
321 	keynameMap.insert( pair<string,SDLKey>("world 95",SDLK_WORLD_95) );
322 
323 	keynameMap.insert( pair<string,SDLKey>("[0]",SDLK_KP0) );
324 	keynameMap.insert( pair<string,SDLKey>("[1]",SDLK_KP1) );
325 	keynameMap.insert( pair<string,SDLKey>("[2]",SDLK_KP2) );
326 	keynameMap.insert( pair<string,SDLKey>("[3]",SDLK_KP3) );
327 	keynameMap.insert( pair<string,SDLKey>("[4]",SDLK_KP4) );
328 	keynameMap.insert( pair<string,SDLKey>("[5]",SDLK_KP5) );
329 	keynameMap.insert( pair<string,SDLKey>("[6]",SDLK_KP6) );
330 	keynameMap.insert( pair<string,SDLKey>("[7]",SDLK_KP7) );
331 	keynameMap.insert( pair<string,SDLKey>("[8]",SDLK_KP8) );
332 	keynameMap.insert( pair<string,SDLKey>("[9]",SDLK_KP9) );
333 	keynameMap.insert( pair<string,SDLKey>("[.]",SDLK_KP_PERIOD) );
334 	keynameMap.insert( pair<string,SDLKey>("[/]",SDLK_KP_DIVIDE) );
335 	keynameMap.insert( pair<string,SDLKey>("[*]",SDLK_KP_MULTIPLY) );
336 	keynameMap.insert( pair<string,SDLKey>("[-]",SDLK_KP_MINUS) );
337 	keynameMap.insert( pair<string,SDLKey>("[+]",SDLK_KP_PLUS) );
338 	keynameMap.insert( pair<string,SDLKey>("enter",SDLK_KP_ENTER) );
339 	keynameMap.insert( pair<string,SDLKey>("equals",SDLK_KP_EQUALS) );
340 
341 	keynameMap.insert( pair<string,SDLKey>("up",SDLK_UP) );
342 	keynameMap.insert( pair<string,SDLKey>("down",SDLK_DOWN) );
343 	keynameMap.insert( pair<string,SDLKey>("right",SDLK_RIGHT) );
344 	keynameMap.insert( pair<string,SDLKey>("left",SDLK_LEFT) );
345 	keynameMap.insert( pair<string,SDLKey>("down",SDLK_DOWN) );
346 	keynameMap.insert( pair<string,SDLKey>("insert",SDLK_INSERT) );
347 	keynameMap.insert( pair<string,SDLKey>("home",SDLK_HOME) );
348 	keynameMap.insert( pair<string,SDLKey>("end",SDLK_END) );
349 	keynameMap.insert( pair<string,SDLKey>("page up",SDLK_PAGEUP) );
350 	keynameMap.insert( pair<string,SDLKey>("page down",SDLK_PAGEDOWN) );
351 
352 	keynameMap.insert( pair<string,SDLKey>("f1",SDLK_F1) );
353 	keynameMap.insert( pair<string,SDLKey>("f2",SDLK_F2) );
354 	keynameMap.insert( pair<string,SDLKey>("f3",SDLK_F3) );
355 	keynameMap.insert( pair<string,SDLKey>("f4",SDLK_F4) );
356 	keynameMap.insert( pair<string,SDLKey>("f5",SDLK_F5) );
357 	keynameMap.insert( pair<string,SDLKey>("f6",SDLK_F6) );
358 	keynameMap.insert( pair<string,SDLKey>("f7",SDLK_F7) );
359 	keynameMap.insert( pair<string,SDLKey>("f8",SDLK_F8) );
360 	keynameMap.insert( pair<string,SDLKey>("f9",SDLK_F9) );
361 	keynameMap.insert( pair<string,SDLKey>("f10",SDLK_F10) );
362 	keynameMap.insert( pair<string,SDLKey>("f11",SDLK_F11) );
363 	keynameMap.insert( pair<string,SDLKey>("f12",SDLK_F12) );
364 	keynameMap.insert( pair<string,SDLKey>("f13",SDLK_F13) );
365 	keynameMap.insert( pair<string,SDLKey>("f14",SDLK_F14) );
366 	keynameMap.insert( pair<string,SDLKey>("f15",SDLK_F15) );
367 
368 	keynameMap.insert( pair<string,SDLKey>("numlock",SDLK_NUMLOCK) );
369 	keynameMap.insert( pair<string,SDLKey>("caps lock",SDLK_CAPSLOCK) );
370 	keynameMap.insert( pair<string,SDLKey>("scroll lock",SDLK_SCROLLOCK) );
371 	keynameMap.insert( pair<string,SDLKey>("right shift",SDLK_RSHIFT) );
372 	keynameMap.insert( pair<string,SDLKey>("left shift",SDLK_LSHIFT) );
373 	keynameMap.insert( pair<string,SDLKey>("right ctrl",SDLK_RCTRL) );
374 	keynameMap.insert( pair<string,SDLKey>("left ctrl",SDLK_LCTRL) );
375 	keynameMap.insert( pair<string,SDLKey>("right alt",SDLK_RALT) );
376 	keynameMap.insert( pair<string,SDLKey>("left alt",SDLK_LALT) );
377 	keynameMap.insert( pair<string,SDLKey>("right meta",SDLK_RMETA) );
378 	keynameMap.insert( pair<string,SDLKey>("left meta",SDLK_LMETA) );
379 	keynameMap.insert( pair<string,SDLKey>("left super",SDLK_LSUPER) );
380 	keynameMap.insert( pair<string,SDLKey>("right super",SDLK_RSUPER) );
381 	keynameMap.insert( pair<string,SDLKey>("alt gr",SDLK_MODE) );
382 	keynameMap.insert( pair<string,SDLKey>("compose",SDLK_COMPOSE) );
383 
384 	keynameMap.insert( pair<string,SDLKey>("help",SDLK_HELP) );
385 	keynameMap.insert( pair<string,SDLKey>("print screen",SDLK_PRINT) );
386 	keynameMap.insert( pair<string,SDLKey>("sys req",SDLK_SYSREQ) );
387 	keynameMap.insert( pair<string,SDLKey>("break",SDLK_BREAK) );
388 	keynameMap.insert( pair<string,SDLKey>("menu",SDLK_MENU) );
389 	keynameMap.insert( pair<string,SDLKey>("power",SDLK_POWER) );
390 	keynameMap.insert( pair<string,SDLKey>("euro",SDLK_EURO) );
391 	keynameMap.insert( pair<string,SDLKey>("undo",SDLK_UNDO) );
392     }
393 
394     mod = KMOD_NONE;
395     size_t oldlen;
396     do {
397 	oldlen = keyString.length();
398 	if (keyString.compare(0, 6, "shift+") == 0)
399 	{ keyString.erase(0, 6); mod = SDLMod(mod | KMOD_SHIFT); }
400 	if (keyString.compare(0, 5, "ctrl+") == 0)
401 	{ keyString.erase(0, 5); mod = SDLMod(mod | KMOD_CTRL); }
402 	if (keyString.compare(0, 4, "alt+") == 0)
403 	{ keyString.erase(0, 4); mod = SDLMod(mod | KMOD_ALT); }
404     } while (keyString.length() < oldlen);
405 
406     map<string,SDLKey,strcomp>::iterator it = keynameMap.find(keyString);
407     if ( it != keynameMap.end() )
408 	sym = it->second;
409     else
410 	sym = SDLK_UNKNOWN;
411 }
412 
getString() const413 string Key::getString() const
414 {
415     if (sym == SDLK_UNKNOWN)
416 	return string("none");
417 
418     string s("");
419 
420     if (mod & KMOD_SHIFT)
421 	s += string("shift+");
422     if (mod & KMOD_CTRL)
423 	s += string("ctrl+");
424     if (mod & KMOD_ALT)
425 	s += string("alt+");
426     s += string(SDL_GetKeyName(sym));
427 
428     return s;
429 }
430 
operator !=(Key const & other) const431 bool Key::operator!=(Key const& other) const
432 {
433     return (!((*this) == other));
434 }
operator ==(Key const & other) const435 bool Key::operator==(Key const& other) const
436 {
437     return (sym == other.sym && mod == other.mod);
438 }
439 
isPressed()440 bool Key::isPressed()
441 {
442     return (SDL_GetKeyState(NULL)[sym] && simpleMod(SDL_GetModState()) == mod);
443 }
444 
445 Key KEY_NONE;
446 
447 // get(command): returns Key bound to command if in the map, else the null Key
get(command com) const448 Key Keybindings::get(command com) const
449 {
450     map<command,Key>::const_iterator it = find(com);
451     if (it == end())
452 	return Key();
453     else
454 	return it->second;
455 }
456 
457 // XXX: see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 if
458 // you're wondering why we don't just make defaultKeybindings an extern
defaultKeybindings()459 Keybindings& defaultKeybindings()
460 {
461     static Keybindings defaultKeybindings;
462     if (defaultKeybindings.empty())
463     {
464 	//initialise
465 	defaultKeybindings[C_LEFT] = Key(SDLK_LEFT);
466 	defaultKeybindings[C_RIGHT] = Key(SDLK_RIGHT);
467 	defaultKeybindings[C_DEZOOM] = Key(SDLK_UP);
468 	defaultKeybindings[C_DEAIM] = Key(SDLK_DOWN);
469 	defaultKeybindings[C_SHOOT_GREEN] = Key(SDLK_1);
470 	defaultKeybindings[C_SHOOT_YELLOW] = Key(SDLK_2);
471 	defaultKeybindings[C_SHOOT_RED] = Key(SDLK_3);
472 	defaultKeybindings[C_SHOOT_POD] = Key(SDLK_4);
473 
474 	defaultKeybindings[C_PAUSE] = Key(SDLK_p);
475 	defaultKeybindings[C_QUIT] = Key(SDLK_q);
476 
477 	defaultKeybindings[C_MENU] = Key(SDLK_ESCAPE);
478 	defaultKeybindings[C_M_LEFT] = Key(SDLK_LEFT);
479 	defaultKeybindings[C_M_UP] = Key(SDLK_UP);
480 	defaultKeybindings[C_M_RIGHT] = Key(SDLK_RIGHT);
481 	defaultKeybindings[C_M_DOWN] = Key(SDLK_DOWN);
482 
483 	defaultKeybindings[C_STARTGAME] = Key(SDLK_SPACE);
484 
485 #ifdef SOUND
486 	defaultKeybindings[C_SOUND] = Key(SDLK_s);
487 #endif
488 
489 	defaultKeybindings[C_ZOOM] = Key(SDLK_z);
490 	defaultKeybindings[C_ROTATE] = Key(SDLK_r);
491 	defaultKeybindings[C_GRID] = Key(SDLK_g);
492 	defaultKeybindings[C_DECAA] = Key(SDLK_a, SDLMod(KMOD_SHIFT));
493 	defaultKeybindings[C_INCAA] = Key(SDLK_a);
494 
495 	defaultKeybindings[C_DECFPS] = Key(SDLK_LEFTBRACKET);
496 	defaultKeybindings[C_INCFPS] = Key(SDLK_RIGHTBRACKET);
497 
498 	defaultKeybindings[C_DECRATE] = Key(SDLK_MINUS);
499 	defaultKeybindings[C_INCRATE] = Key(SDLK_EQUALS, SDLMod(KMOD_SHIFT));
500 	defaultKeybindings[C_RESETRATE] = Key(SDLK_EQUALS);
501 
502 #ifdef HIGH_SCORE_REPORTING
503 	defaultKeybindings[C_REPORTHS] = Key(SDLK_F10);
504 #endif
505 
506 	defaultKeybindings[C_SCREENSHOT] = Key(SDLK_F12);
507 
508 	defaultKeybindings[C_INVULN] = Key(SDLK_F4);
509 	defaultKeybindings[C_WIN] = Key(SDLK_F5);
510     }
511 
512     return defaultKeybindings;
513 }
514 
515