11 #include "enabler_input.h"
16 #include "find_files.h"
20 // The timeline events we actually pass back from get_input. Well, no,
21 // that's just k, but..
25 int repeats
; // Starts at 0, increments once per repeat
28 int tick
; // The sim-tick at which we last returned this event
29 bool macro
; // Created as part of macro playback.
31 bool operator== (const Event
&other
) const {
32 if (r
!= other
.r
) return false;
33 if (k
!= other
.k
) return false;
34 if (repeats
!= other
.repeats
) return false;
35 if (serial
!= other
.serial
) return false;
36 if (time
!= other
.time
) return false;
37 if (macro
!= other
.macro
) return false;
41 // We sort by time first, and then serial number.
42 // The order of the other bits is unimportant.
43 bool operator< (const Event
&o
) const {
44 if (time
!= o
.time
) return time
< o
.time
;
45 if (serial
!= o
.serial
) return serial
< o
.serial
;
46 if (r
!= o
.r
) return r
< o
.r
;
47 if (k
!= o
.k
) return k
< o
.k
;
48 if (repeats
!= o
.repeats
) return repeats
< o
.repeats
;
49 if (macro
!= o
.macro
) return macro
< o
.macro
;
54 // Used to decide which key-binding to display. As a heuristic, we
55 // prefer whichever display string is shortest.
57 bool operator() (const string
&a
, const string
&b
) const {
58 if (a
.size() < b
.size()) return true;
59 if (a
.size() > b
.size()) return false;
64 // These change dynamically in the normal process of DF
65 static int last_serial
= 0; // Input serial number, to differentiate distinct physical presses
66 static set
<Event
> timeline
; // A timeline of pending key events (for next get_input)
67 static set
<EventMatch
> pressed_keys
; // Keys we consider "pressed"
68 static int modState
; // Modifier state
70 // These do not change as part of the normal dynamics of DF, only at startup/when editing.
71 static multimap
<EventMatch
,InterfaceKey
> keymap
;
72 static map
<InterfaceKey
,Repeat
> repeatmap
;
73 static map
<InterfaceKey
,set
<string
,less_sz
> > keydisplay
; // Used only for display, not for meaning
76 static bool macro_recording
= false;
77 static macro active_macro
; // Active macro
78 static map
<string
,macro
> macros
;
79 static Time macro_end
= 0; // Time at which the currently playing macro will end
81 // Prefix command state
82 static bool in_prefix_command
= false;
83 static string prefix_command
;
86 static bool key_registering
= false;
87 static list
<EventMatch
> stored_keys
;
89 // Interface-file last loaded
90 static string interfacefile
;
93 // Returns an unused serial number
94 static Time
next_serial() {
98 static void update_keydisplay(InterfaceKey binding
, string display
) {
99 // Need to filter out space/tab, for obvious reasons.
100 if (display
== " ") display
= "Space";
101 if (display
== "\t") display
= "Tab";
102 map
<InterfaceKey
,set
<string
,less_sz
> >::iterator it
= keydisplay
.find(binding
);
103 if (it
== keydisplay
.end()) {
104 set
<string
,less_sz
> s
; s
.insert(display
);
105 keydisplay
[binding
] = s
;
107 keydisplay
[binding
].insert(display
);
111 static void assertgood(ifstream
&s
) {
113 MessageBox(NULL
, "EOF while parsing keyboard bindings", 0, 0);
115 MessageBox(NULL
, "I/O error while parsing keyboard bindings", 0, 0);
121 // Decodes an UTF-8 encoded string into a /single/ UTF-8 character,
122 // discarding any overflow. Returns 0 on parse error.
123 int decode_utf8(const string
&s
) {
124 int unicode
= 0, length
, i
;
125 if (s
.length() == 0) return 0;
126 length
= decode_utf8_predict_length(s
[0]);
128 case 1: unicode
= s
[0]; break;
129 case 2: unicode
= s
[0] & 0x1f; break;
130 case 3: unicode
= s
[0] & 0x0f; break;
131 case 4: unicode
= s
[0] & 0x07; break;
135 // Concatenate the follow-up bytes
136 if (s
.length() < length
) return 0;
137 for (i
= 1; i
< length
; i
++) {
138 if ((s
[i
] & 0xc0) != 0x80) return 0;
139 unicode
= (unicode
<< 6) | (s
[i
] & 0x3f);
144 // Returns the length of an utf-8 sequence, based on its first byte
145 int decode_utf8_predict_length(char byte
) {
146 if ((byte
& 0x80) == 0) return 1;
147 if ((byte
& 0xe0) == 0xc0) return 2;
148 if ((byte
& 0xf0) == 0xe0) return 3;
149 if ((byte
& 0xf8) == 0xf0) return 4;
150 return 0; // Invalid start byte
153 // Encode an arbitrary unicode value as a string. Returns an empty
154 // string if the value is out of range.
155 string
encode_utf8(int unicode
) {
158 if (unicode
< 0 || unicode
> 0x10ffff) return ""; // Out of range for utf-8
159 else if (unicode
<= 0x007f) { // 1-byte utf-8
162 else if (unicode
<= 0x07ff) { // 2-byte utf-8
166 else if (unicode
<= 0xffff) { // 3-byte utf-8
170 else { // 4-byte utf-8
175 // Build up the string, right to left
176 for (i
= s
.length()-1; i
> 0; i
--) {
177 s
[i
] = 0x80 | (unicode
& 0x3f);
180 // Finally, what's left goes in the low bits of s[0]
185 string
translate_mod(Uint8 mod
) {
187 if (mod
& 1) ret
+= "Shift+";
188 if (mod
& 2) ret
+= "Ctrl+";
189 if (mod
& 4) ret
+= "Alt+";
193 static string
display(const EventMatch
&match
) {
195 ret
<< translate_mod(match
.mod
);
196 switch (match
.type
) {
197 case type_unicode
: ret
<< (char)match
.unicode
; break;
199 map
<SDLKey
,string
>::iterator it
= sdlNames
.left
.find(match
.key
);
200 if (it
!= sdlNames
.left
.end())
203 ret
<< "SDL+" << (int)match
.key
;
207 ret
<< "Button " << (int)match
.button
;
213 static string
translate_repeat(Repeat r
) {
215 case REPEAT_NOT
: return "REPEAT_NOT";
216 case REPEAT_SLOW
: return "REPEAT_SLOW";
217 case REPEAT_FAST
: return "REPEAT_FAST";
218 default: return "REPEAT_BROKEN";
222 // Update the modstate, since SDL_getModState doesn't /work/ for alt
223 static void update_modstate(const SDL_Event
&e
) {
224 if (e
.type
== SDL_KEYUP
) {
225 switch (e
.key
.keysym
.sym
) {
239 } else if (e
.type
== SDL_KEYDOWN
) {
240 switch (e
.key
.keysym
.sym
) {
257 // Converts SDL mod states to ours, collapsing left/right shift/alt/ctrl
258 Uint8
getModState() {
262 // Not sure what to call this, but it ain't using regexes.
263 static bool parse_line(const string
&line
, const string
®ex
, vector
<string
> &parts
) {
265 parts
.push_back(line
);
267 for (int l
= 0, r
= 0; r
< regex
.length();) {
269 case '*': // Read until ], : or the end of the line, but at least one character.
272 for (; l
< line
.length() && (l
== start
|| (line
[l
] != ']' && line
[l
] != ':')); l
++)
274 parts
.push_back(line
.substr(start
, l
- start
));
279 if (line
[l
] != regex
[r
]) return false;
284 // We've made it this far, clearly the string parsed
288 void enabler_inputst::load_keybindings(const string
&file
) {
289 cout
<< "Loading bindings from " << file
<< endl
;
290 interfacefile
= file
;
291 ifstream
s(file
.c_str());
293 MessageBox(NULL
, (file
+ " not found, or I/O error encountered").c_str(), 0, 0);
301 lines
.push_back(line
);
304 static const string
bind("[BIND:*:*]");
305 static const string
sym("[SYM:*:*]");
306 static const string
key("[KEY:*]");
307 static const string
button("[BUTTON:*:*]");
309 list
<string
>::iterator line
= lines
.begin();
310 vector
<string
> match
;
312 while (line
!= lines
.end()) {
313 if (parse_line(*line
, bind
, match
)) {
314 map
<string
,InterfaceKey
>::iterator it
= bindingNames
.right
.find(match
[1]);
315 if (it
!= bindingNames
.right
.end()) {
316 InterfaceKey binding
= it
->second
;
318 if (match
[2] == "REPEAT_FAST")
319 repeatmap
[(InterfaceKey
)binding
] = REPEAT_FAST
;
320 else if (match
[2] == "REPEAT_SLOW")
321 repeatmap
[(InterfaceKey
)binding
] = REPEAT_SLOW
;
322 else if (match
[2] == "REPEAT_NOT")
323 repeatmap
[(InterfaceKey
)binding
] = REPEAT_NOT
;
325 repeatmap
[(InterfaceKey
)binding
] = REPEAT_NOT
;
326 cout
<< "Broken repeat request: " << match
[2] << endl
;
329 // Add symbols/keys/buttons
330 while (line
!= lines
.end()) {
333 if (parse_line(*line
, sym
, match
)) {
334 map
<string
,SDLKey
>::iterator it
= sdlNames
.right
.find(match
[2]);
335 if (it
!= sdlNames
.right
.end()) {
336 matcher
.mod
= atoi(string(match
[1]).c_str());
337 matcher
.type
= type_key
;
338 matcher
.key
= it
->second
;
339 keymap
.insert(pair
<EventMatch
,InterfaceKey
>(matcher
, (InterfaceKey
)binding
));
340 update_keydisplay(binding
, display(matcher
));
342 cout
<< "Unknown SDLKey: " << match
[2] << endl
;
346 else if (parse_line(*line
, key
, match
)) {
347 matcher
.type
= type_unicode
;
348 matcher
.unicode
= decode_utf8(match
[1]);
349 matcher
.mod
= KMOD_NONE
;
350 if (matcher
.unicode
) {
351 keymap
.insert(make_pair(matcher
, (InterfaceKey
)binding
));
352 if (matcher
.unicode
< 256) {
353 // This unicode key is part of the latin-1 mapped portion of unicode, so we can
354 // actually display it. Nice.
355 char c
[2] = {char(matcher
.unicode
), 0};
356 update_keydisplay(binding
, display(matcher
));
359 cout
<< "Broken unicode: " << *line
<< endl
;
363 else if (parse_line(*line
, button
, match
)) {
364 matcher
.type
= type_button
;
365 string str
= match
[2];
366 matcher
.button
= atoi(str
.c_str());
367 if (matcher
.button
) {
368 matcher
.mod
= atoi(string(match
[1]).c_str());
369 keymap
.insert(pair
<EventMatch
,InterfaceKey
>(matcher
, (InterfaceKey
)binding
));
370 update_keydisplay(binding
, display(matcher
));
372 cout
<< "Broken button (should be [BUTTON:#:#]): " << *line
<< endl
;
380 cout
<< "Unknown binding: " << match
[1] << endl
;
384 // Retry with next line
390 void enabler_inputst::save_keybindings(const string
&file
) {
391 cout
<< "Saving bindings to " << file
<< endl
;
392 string temporary
= file
+ ".partial";
393 ofstream
s(temporary
.c_str());
394 multimap
<InterfaceKey
,EventMatch
> map
;
395 InterfaceKey last_key
= INTERFACEKEY_NONE
;
398 string t
= "Failed to open " + temporary
+ " for writing";
399 MessageBox(NULL
, t
.c_str(), 0, 0);
403 // Invert keyboard map
404 for (multimap
<EventMatch
,InterfaceKey
>::iterator it
= keymap
.begin(); it
!= keymap
.end(); ++it
)
405 map
.insert(pair
<InterfaceKey
,EventMatch
>(it
->second
,it
->first
));
406 // Insert an empty line for the benefit of note/wordpad
409 for (multimap
<InterfaceKey
,EventMatch
>::iterator it
= map
.begin(); it
!= map
.end(); ++it
) {
411 MessageBox(NULL
, "I/O error while writing keyboard mapping", 0, 0);
415 if (it
->first
!= last_key
) {
416 last_key
= it
->first
;
417 s
<< "[BIND:" << bindingNames
.left
[it
->first
] << ":"
418 << translate_repeat(repeatmap
[it
->first
]) << "]" << endl
;
420 switch (it
->second
.type
) {
422 s
<< "[KEY:" << encode_utf8(it
->second
.unicode
) << "]" << endl
;
425 s
<< "[SYM:" << (int)it
->second
.mod
<< ":" << sdlNames
.left
[it
->second
.key
] << "]" << endl
;
428 s
<< "[BUTTON:" << (int)it
->second
.mod
<< ":" << (int)it
->second
.button
<< "]" << endl
;
433 replace_file(temporary
, file
);
436 void enabler_inputst::save_keybindings() {
437 save_keybindings(interfacefile
);
440 void enabler_inputst::add_input(SDL_Event
&e
, Uint32 now
) {
441 // Before we can use this input, there are some issues to deal with:
442 // - SDL provides unicode translations only for key-press events, not
443 // releases. We need to keep track of pressed keys, and generate
444 // unicode release events whenever any modifiers are hit, or if
445 // that raw keycode is released.
446 // - Generally speaking, when modifiers are hit/released, we discard those
447 // events and generate press/release events for all pressed non-modifiers.
448 // - It's possible for multiple events to be generated on the same tick.
449 // These are of course separate keypresses, and must be kept separate.
450 // That's what the serial is for.
452 set
<EventMatch
>::iterator pkit
;
453 list
<pair
<KeyEvent
, int> > synthetics
;
456 // Convert modifier state changes
457 if ((e
.type
== SDL_KEYUP
|| e
.type
== SDL_KEYDOWN
) &&
458 (e
.key
.keysym
.sym
== SDLK_RSHIFT
||
459 e
.key
.keysym
.sym
== SDLK_LSHIFT
||
460 e
.key
.keysym
.sym
== SDLK_RCTRL
||
461 e
.key
.keysym
.sym
== SDLK_LCTRL
||
462 e
.key
.keysym
.sym
== SDLK_RALT
||
463 e
.key
.keysym
.sym
== SDLK_LALT
)) {
464 for (pkit
= pressed_keys
.begin(); pkit
!= pressed_keys
.end(); ++pkit
) {
465 // Release currently pressed keys
467 synth
.release
= true;
469 synthetics
.push_back(make_pair(synth
, next_serial()));
470 // Re-press them, with new modifiers, if they aren't unicode. We can't re-translate unicode.
471 if (synth
.match
.type
!= type_unicode
) {
472 synth
.release
= false;
473 synth
.match
.mod
= getModState();
474 if (!key_registering
) // We don't want extras when registering keys
475 synthetics
.push_back(make_pair(synth
, next_serial()));
479 // It's not a modifier. If this is a key release, then we still need
480 // to find and release pressed unicode keys with this scancode
481 if (e
.type
== SDL_KEYUP
) {
482 for (pkit
= pressed_keys
.begin(); pkit
!= pressed_keys
.end(); ++pkit
) {
483 if (pkit
->type
== type_unicode
&& pkit
->scancode
== e
.key
.keysym
.scancode
) {
485 synth
.release
= true;
487 synthetics
.push_back(make_pair(synth
, next_serial()));
491 // Since it's not a modifier, we also pass on symbolic/button
492 // (always) and unicode (if defined) events
494 // However, since SDL ignores(?) ctrl and alt when translating to
495 // unicode, we want to ignore unicode events if those are set.
496 const int serial
= next_serial();
499 real
.release
= (e
.type
== SDL_KEYUP
|| e
.type
== SDL_MOUSEBUTTONUP
) ? true : false;
500 real
.match
.mod
= getModState();
501 if (e
.type
== SDL_MOUSEBUTTONUP
|| e
.type
== SDL_MOUSEBUTTONDOWN
) {
502 real
.match
.type
= type_button
;
503 real
.match
.scancode
= 0;
504 real
.match
.button
= e
.button
.button
;
505 synthetics
.push_back(make_pair(real
, serial
));
507 if (e
.type
== SDL_KEYUP
|| e
.type
== SDL_KEYDOWN
) {
508 real
.match
.type
= type_key
;
509 real
.match
.scancode
= e
.key
.keysym
.scancode
;
510 real
.match
.key
= e
.key
.keysym
.sym
;
511 synthetics
.push_back(make_pair(real
, serial
));
513 if (e
.type
== SDL_KEYDOWN
&& e
.key
.keysym
.unicode
&& getModState() < 2) {
514 real
.match
.mod
= KMOD_NONE
;
515 real
.match
.type
= type_unicode
;
516 real
.match
.scancode
= e
.key
.keysym
.scancode
;
517 real
.match
.unicode
= e
.key
.keysym
.unicode
;
518 synthetics
.push_back(make_pair(real
, serial
));
520 if (e
.type
== SDL_QUIT
) {
521 // This one, we insert directly into the timeline.
522 Event e
= {REPEAT_NOT
, (InterfaceKey
)INTERFACEKEY_OPTIONS
, 0, next_serial(), now
, 0};
527 list
<pair
<KeyEvent
, int> >::iterator lit
;
528 for (lit
= synthetics
.begin(); lit
!= synthetics
.end(); ++lit
) {
529 // Add or remove the key from pressed_keys, keeping that up to date
530 if (lit
->first
.release
) pressed_keys
.erase(lit
->first
.match
);
531 else pressed_keys
.insert(lit
->first
.match
);
532 // And pass the event on deeper.
533 add_input_refined(lit
->first
, now
, lit
->second
);
538 // 1 and up are ncurses symbols, as returned by getch.
539 // -1 and down are unicode values.
540 // esc is true if this key was part of an escape sequence.
542 void enabler_inputst::add_input_ncurses(int key
, Time now
, bool esc
) {
543 // TODO: Deal with shifted arrow keys, etc. See man 5 terminfo and tgetent.
545 EventMatch sdl
, uni
; // Each key may provoke an unicode event, an "SDL-key" event, or both
546 const int serial
= next_serial();
548 uni
.type
= type_unicode
;
549 sdl
.scancode
= uni
.scancode
= 0; // We don't use this.. hang on, who does? ..nobody. FIXME!
550 sdl
.mod
= uni
.mod
= 0;
551 sdl
.key
= SDLK_UNKNOWN
;
554 if (esc
) { // Escape sequence, meaning alt was held. I hope.
555 sdl
.mod
= uni
.mod
= DFMOD_ALT
;
558 if (key
== -10) { // Return
559 sdl
.key
= SDLK_RETURN
;
561 } else if (key
== -9) { // Tab
564 } else if (key
== -27) { // If we see esc here, it's the actual esc key. Hopefully.
565 sdl
.key
= SDLK_ESCAPE
;
566 } else if (key
== -127) { // Backspace/del
567 sdl
.key
= SDLK_BACKSPACE
;
568 } else if (key
< 0 && key
>= -26) { // Control-a through z (but not ctrl-j, or ctrl-i)
569 sdl
.mod
|= DFMOD_CTRL
;
570 sdl
.key
= (SDLKey
)(SDLK_a
+ (-key
) - 1);
571 } else if (key
<= -32 && key
>= -126) { // ASCII character set
573 sdl
.key
= (SDLKey
)-key
; // Most of this maps directly to SDL keys, except..
574 if (sdl
.key
> 64 && sdl
.key
< 91) { // Uppercase
575 sdl
.key
= (SDLKey
)(sdl
.key
+ 32); // Maps to lowercase, and
576 sdl
.mod
|= DFMOD_SHIFT
; // Add shift.
578 } else if (key
< -127) { // Unicode, no matching SDL keys
580 } else if (key
> 0) { // Symbols such as arrow-keys, etc, no matching unicode.
582 case KEY_DOWN
: sdl
.key
= SDLK_DOWN
; break;
583 case KEY_UP
: sdl
.key
= SDLK_UP
; break;
584 case KEY_LEFT
: sdl
.key
= SDLK_LEFT
; break;
585 case KEY_RIGHT
: sdl
.key
= SDLK_RIGHT
; break;
586 case KEY_BACKSPACE
: sdl
.key
= SDLK_BACKSPACE
; break;
587 case KEY_F(1): sdl
.key
= SDLK_F1
; break;
588 case KEY_F(2): sdl
.key
= SDLK_F2
; break;
589 case KEY_F(3): sdl
.key
= SDLK_F3
; break;
590 case KEY_F(4): sdl
.key
= SDLK_F4
; break;
591 case KEY_F(5): sdl
.key
= SDLK_F5
; break;
592 case KEY_F(6): sdl
.key
= SDLK_F6
; break;
593 case KEY_F(7): sdl
.key
= SDLK_F7
; break;
594 case KEY_F(8): sdl
.key
= SDLK_F8
; break;
595 case KEY_F(9): sdl
.key
= SDLK_F9
; break;
596 case KEY_F(10): sdl
.key
= SDLK_F10
; break;
597 case KEY_F(11): sdl
.key
= SDLK_F11
; break;
598 case KEY_F(12): sdl
.key
= SDLK_F12
; break;
599 case KEY_F(13): sdl
.key
= SDLK_F13
; break;
600 case KEY_F(14): sdl
.key
= SDLK_F14
; break;
601 case KEY_F(15): sdl
.key
= SDLK_F15
; break;
602 case KEY_DC
: sdl
.key
= SDLK_DELETE
; break;
603 case KEY_NPAGE
: sdl
.key
= SDLK_PAGEDOWN
; break;
604 case KEY_PPAGE
: sdl
.key
= SDLK_PAGEUP
; break;
605 case KEY_ENTER
: sdl
.key
= SDLK_RETURN
; break;
609 // We may be registering a new mapping, in which case we skip the
610 // rest of this function.
611 if (key_registering
) {
613 stored_keys
.push_back(uni
);
616 stored_keys
.push_back(sdl
);
618 Event e
; e
.r
= REPEAT_NOT
; e
.repeats
= 0; e
.time
= now
; e
.serial
= serial
; e
.k
= INTERFACEKEY_KEYBINDING_COMPLETE
; e
.tick
= enabler
.simticks
.read();
620 key_registering
= false;
624 // Key repeat is handled by the terminal, and we don't get release
626 KeyEvent kev
; kev
.release
= false;
627 Event e
; e
.r
= REPEAT_NOT
; e
.repeats
= 0; e
.time
= now
;
629 set
<InterfaceKey
> events
= key_translation(sdl
);
630 for (set
<InterfaceKey
>::iterator k
= events
.begin(); k
!= events
.end(); ++k
) {
637 set
<InterfaceKey
> events
= key_translation(uni
);
638 for (set
<InterfaceKey
>::iterator k
= events
.begin(); k
!= events
.end(); ++k
) {
647 void enabler_inputst::add_input_refined(KeyEvent
&e
, Uint32 now
, int serial
) {
648 // We may be registering a new mapping, in which case we skip the
649 // rest of this function.
650 if (key_registering
&& !e
.release
) {
651 stored_keys
.push_back(e
.match
);
652 Event e
; e
.r
= REPEAT_NOT
; e
.repeats
= 0; e
.time
= now
; e
.serial
= serial
; e
.k
= INTERFACEKEY_KEYBINDING_COMPLETE
; e
.tick
= enabler
.simticks
.read();
657 // If this is a key-press event, we add it to the timeline. If it's
658 // a release, we remove any pending repeats, but not those that
659 // haven't repeated yet (which are on their first cycle); those we
660 // just set to non-repeating.
661 set
<InterfaceKey
> keys
= key_translation(e
.match
);
663 set
<Event
>::iterator it
= timeline
.begin();
664 while (it
!= timeline
.end()) {
665 set
<Event
>::iterator el
= it
++;
666 if (keys
.count(el
->k
)) {
671 new_el
.r
= REPEAT_NOT
;
673 timeline
.insert(new_el
);
678 set
<InterfaceKey
>::iterator key
;
679 // As policy, when the user hits a non-repeating key we'd want to
680 // also cancel any keys that are currently repeating. This allows
681 // for easy recovery from stuck keys.
683 // Unfortunately, each key may be bound to multiple
684 // commands. So, lacking information on which commands are
685 // accepted at the moment, there is no way we can know if it's
686 // okay to cancel repeats unless /all/ the bindings are
688 for (set
<InterfaceKey
>::iterator k
= keys
.begin(); k
!= keys
.end(); ++k
) {
689 Event e
= {key_repeat(*k
), *k
, 0, serial
, now
, enabler
.simticks
.read()};
693 // // Set everything on the timeline to non-repeating
694 // multimap<Time,Event>::iterator it;
695 // for (it = timeline.begin(); it != timeline.end(); ++it) {
696 // it->second.r = REPEAT_NOT;
702 void enabler_inputst::clear_input() {
704 pressed_keys
.clear();
709 set
<InterfaceKey
> enabler_inputst::get_input(Time now
) {
710 // We walk the timeline, returning all events corresponding to a
711 // single physical keypress, and inserting repeats relative to the
712 // current time, not when the events we're now returning were
713 // *supposed* to happen.
715 set
<InterfaceKey
> input
;
716 set
<Event
>::iterator ev
= timeline
.begin();
717 if (ev
== timeline
.end() || ev
->time
> now
) {
718 return input
; // No input (yet).
721 const Time first_time
= ev
->time
;
722 const int first_serial
= ev
->serial
;
723 int simtick
= enabler
.simticks
.read();
724 bool event_from_macro
= false;
725 while (ev
!= timeline
.end() && ev
->time
== first_time
&& ev
->serial
== first_serial
) {
726 // Avoid recording macro-sources events as macro events.
727 if (ev
->macro
) event_from_macro
= true;
728 // To make sure the user had a chance to cancel (by lifting the key), we require there
729 // to be at least three simulation ticks before the first repeat.
730 if (ev
->repeats
== 1 && ev
->tick
> simtick
- 3) {
741 if (ev
->repeats
== 0) {
742 next
.time
= now
+ init
.input
.hold_time
;
743 timeline
.insert(next
);
748 if (ev
->repeats
>= init
.input
.repeat_accel_start
) {
749 // Compute acceleration
750 accel
= MIN(init
.input
.repeat_accel_limit
,
751 sqrt(double(next
.repeats
- init
.input
.repeat_accel_start
) + 16) - 3);
753 next
.time
= now
+ double(init
.input
.repeat_time
) / accel
;
754 timeline
.insert(next
);
757 // Delete the event from the timeline and iterate
758 timeline
.erase(ev
++);
761 if (input
.size() && !init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
762 cout
<< "Returning input:\n";
763 set
<InterfaceKey
>::iterator it
;
764 for (it
= input
.begin(); it
!= input
.end(); ++it
)
765 cout
<< " " << GetKeyDisplay(*it
) << ": " << GetBindingDisplay(*it
) << endl
;
768 // It could be argued that the "record event" step of recording
769 // belongs in add_input, not here. I don't hold with this
770 // argument. The whole point is to record events as the user seems
772 if (macro_recording
&& !event_from_macro
) {
773 set
<InterfaceKey
> macro_input
= input
;
774 macro_input
.erase(INTERFACEKEY_RECORD_MACRO
);
775 macro_input
.erase(INTERFACEKEY_PLAY_MACRO
);
776 macro_input
.erase(INTERFACEKEY_SAVE_MACRO
);
777 macro_input
.erase(INTERFACEKEY_LOAD_MACRO
);
778 if (macro_input
.size())
779 active_macro
.push_back(macro_input
);
784 set
<InterfaceKey
> enabler_inputst::key_translation(EventMatch
&match
) {
785 set
<InterfaceKey
> bindings
;
786 pair
<multimap
<EventMatch
,InterfaceKey
>::iterator
,multimap
<EventMatch
,InterfaceKey
>::iterator
> its
;
788 for (its
= keymap
.equal_range(match
); its
.first
!= its
.second
; ++its
.first
)
789 bindings
.insert((its
.first
)->second
);
794 string
enabler_inputst::GetKeyDisplay(int binding
) {
795 map
<InterfaceKey
,set
<string
,less_sz
> >::iterator it
= keydisplay
.find(binding
);
796 if (it
!= keydisplay
.end() && it
->second
.size())
797 return *it
->second
.begin();
799 cout
<< "Missing binding displayed: " + bindingNames
.left
[binding
] << endl
;
804 string
enabler_inputst::GetBindingDisplay(int binding
) {
805 map
<InterfaceKey
,string
>::iterator it
= bindingNames
.left
.find(binding
);
806 if (it
!= bindingNames
.left
.end())
812 string
enabler_inputst::GetBindingTextDisplay(int binding
) {
813 map
<InterfaceKey
,string
>::iterator it
= displayNames
.left
.find(binding
);
814 if (it
!=displayNames
.left
.end())
820 Repeat
enabler_inputst::key_repeat(InterfaceKey binding
) {
821 map
<InterfaceKey
,Repeat
>::iterator it
= repeatmap
.find(binding
);
822 if (it
!= repeatmap
.end())
828 void enabler_inputst::key_repeat(InterfaceKey binding
, Repeat repeat
) {
829 repeatmap
[binding
] = repeat
;
832 void enabler_inputst::record_input() {
833 active_macro
.clear();
834 macro_recording
= true;
837 void enabler_inputst::record_stop() {
838 macro_recording
= false;
841 bool enabler_inputst::is_recording() {
842 return macro_recording
;
845 void enabler_inputst::play_macro() {
846 Time now
= SDL_GetTicks();
847 for(set
<Event
>::iterator i
= timeline
.begin(); i
!= timeline
.end(); i
++){
848 now
= MAX(now
, (*i
).time
);
850 for (macro::iterator sim
= active_macro
.begin(); sim
!= active_macro
.end(); ++sim
) {
851 Event e
; e
.r
= REPEAT_NOT
; e
.repeats
= 0; e
.serial
= next_serial(); e
.time
= now
;
852 e
.macro
= true; // Avoid exponential macro blowup.
853 for (set
<InterfaceKey
>::iterator k
= sim
->begin(); k
!= sim
->end(); ++k
) {
856 now
+= init
.input
.macro_time
;
859 macro_end
= MAX(macro_end
, now
);
862 bool enabler_inputst::is_macro_playing() {
863 return SDL_GetTicks() <= macro_end
;
866 // Replaces any illegal letters.
867 static string
filter_filename(string name
, char replacement
) {
868 for (int i
= 0; i
< name
.length(); i
++) {
870 case '<': name
[i
] = replacement
; break;
871 case '>': name
[i
] = replacement
; break;
872 case ':': name
[i
] = replacement
; break;
873 case '"': name
[i
] = replacement
; break;
874 case '/': name
[i
] = replacement
; break;
875 case '\\': name
[i
] = replacement
; break;
876 case '|': name
[i
] = replacement
; break;
877 case '?': name
[i
] = replacement
; break;
878 case '*': name
[i
] = replacement
; break;
880 if (name
[i
] <= 31) name
[i
] = replacement
;
885 void enabler_inputst::load_macro_from_file(const string
&file
) {
886 ifstream
s(file
.c_str());
890 if (macros
.find(name
) != macros
.end()) return; // Already got it.
893 set
<InterfaceKey
> group
;
897 MessageBox(NULL
, "I/O error while loading macro", 0, 0);
902 if (line
== "End of macro") {
903 if (group
.size()) macro
.push_back(group
);
905 } else if (line
== "\tEnd of group") {
906 if (group
.size()) macro
.push_back(group
);
908 } else if (line
.substr(0,2) != "\t\t" ) {
909 if( line
.substr(1).find("\t") != string::npos
) {
910 // expecting /t##/tCMD for a repeated command
911 istringstream
ss(line
.substr(1));
913 string remainingline
;
917 if(remainingline
.size()) {
918 for(int i
=0; i
< count
; i
++) {
919 map
<string
,InterfaceKey
>::iterator it
= bindingNames
.right
.find(remainingline
);
920 if (it
== bindingNames
.right
.end()) {
921 cout
<< "Binding name unknown while loading macro: " << line
.substr(1) << endl
;
923 group
.insert(it
->second
);
924 if (group
.size()) macro
.push_back(group
);
930 cout
<< "Binding missing while loading macro: " << line
.substr(1) << endl
;
933 cout
<< "Quantity not numeric or Unexpected tab(s) while loading macro: " << line
.substr(1) << endl
;
938 // expecting /tCMD for a non-grouped command
939 map
<string
,InterfaceKey
>::iterator it
= bindingNames
.right
.find(line
.substr(1));
940 if (it
== bindingNames
.right
.end()) {
941 cout
<< "Binding name unknown while loading macro: " << line
.substr(1) << endl
;
943 group
.insert(it
->second
);
944 if (group
.size()) macro
.push_back(group
);
949 map
<string
,InterfaceKey
>::iterator it
= bindingNames
.right
.find(line
.substr(2));
950 if (it
== bindingNames
.right
.end())
951 cout
<< "Binding name unknown while loading macro: " << line
.substr(2) << endl
;
953 group
.insert(it
->second
);
957 macros
[name
] = macro
;
959 MessageBox(NULL
, "I/O error while loading macro", 0, 0);
963 void enabler_inputst::save_macro_to_file(const string
&file
, const string
&name
, const macro
¯o
) {
964 ofstream
s(file
.c_str());
966 for (macro::const_iterator group
= macro
.begin(); group
!= macro
.end(); ++group
) {
967 for (set
<InterfaceKey
>::const_iterator key
= group
->begin(); key
!= group
->end(); ++key
)
968 s
<< "\t\t" << bindingNames
.left
[*key
] << endl
;
969 s
<< "\tEnd of group" << endl
;
971 s
<< "End of macro" << endl
;
975 list
<string
> enabler_inputst::list_macros() {
976 // First, check for unloaded macros
977 svector
<char*> files
;
978 find_files_by_pattern("data/init/macros/*.mak", files
);
979 for (int i
= 0; i
< files
.size(); i
++) {
980 string
file(files
[i
]);
982 file
= "data/init/macros/" + file
;
983 load_macro_from_file(file
);
985 // Then return all in-memory macros
987 for (map
<string
,macro
>::iterator it
= macros
.begin(); it
!= macros
.end(); ++it
)
988 ret
.push_back(it
->first
);
992 void enabler_inputst::load_macro(string name
) {
993 if (macros
.find(name
) != macros
.end())
994 active_macro
= macros
[name
];
999 void enabler_inputst::save_macro(string name
) {
1000 macros
[name
] = active_macro
;
1001 save_macro_to_file("data/init/macros/" + filter_filename(name
, '_') + ".mak", name
, active_macro
);
1004 void enabler_inputst::delete_macro(string name
) {
1005 map
<string
,macro
>::iterator it
= macros
.find(name
);
1006 if (it
!= macros
.end()) macros
.erase(it
);
1007 // TODO: Store the filename it was loaded from instead
1008 string filename
= "data/init/macros/" + filter_filename(name
, '_') + ".mak";
1009 remove(filename
.c_str());
1013 // Sets the next key-press to be stored instead of executed.
1014 void enabler_inputst::register_key() {
1015 key_registering
= true;
1016 stored_keys
.clear();
1019 // Returns a description of stored keys. Max one of each type.
1020 list
<RegisteredKey
> enabler_inputst::getRegisteredKey() {
1021 key_registering
= false;
1022 list
<RegisteredKey
> ret
;
1023 for (list
<EventMatch
>::iterator it
= stored_keys
.begin(); it
!= stored_keys
.end(); ++it
) {
1024 struct RegisteredKey r
= {it
->type
, display(*it
)};
1030 // Binds one of the stored keys to key
1031 void enabler_inputst::bindRegisteredKey(MatchType type
, InterfaceKey key
) {
1032 for (list
<EventMatch
>::iterator it
= stored_keys
.begin(); it
!= stored_keys
.end(); ++it
) {
1033 if (it
->type
== type
) {
1034 keymap
.insert(pair
<EventMatch
,InterfaceKey
>(*it
, key
));
1035 update_keydisplay(key
, display(*it
));
1040 bool enabler_inputst::is_registering() {
1041 return key_registering
;
1045 list
<EventMatch
> enabler_inputst::list_keys(InterfaceKey key
) {
1046 list
<EventMatch
> ret
;
1047 // Oh, now this is inefficient.
1048 for (multimap
<EventMatch
,InterfaceKey
>::iterator it
= keymap
.begin(); it
!= keymap
.end(); ++it
)
1049 if (it
->second
== key
) ret
.push_back(it
->first
);
1053 void enabler_inputst::remove_key(InterfaceKey key
, EventMatch ev
) {
1054 for (multimap
<EventMatch
,InterfaceKey
>::iterator it
= keymap
.find(ev
);
1055 it
!= keymap
.end() && it
->first
== ev
;
1057 if (it
->second
== key
) keymap
.erase(it
++);
1059 // Also remove the key from key displaying, assuming we can find it
1060 map
<InterfaceKey
,set
<string
,less_sz
> >::iterator it
= keydisplay
.find(key
);
1061 if (it
!= keydisplay
.end())
1062 it
->second
.erase(display(ev
));
1065 bool enabler_inputst::prefix_building() {
1066 return in_prefix_command
;
1069 void enabler_inputst::prefix_toggle() {
1070 in_prefix_command
= !in_prefix_command
;
1071 prefix_command
.clear();
1074 void enabler_inputst::prefix_add_digit(char digit
) {
1075 prefix_command
.push_back(digit
);
1077 cout
<< "Built prefix to " << prefix_command
<< endl
;
1079 if (atoi(prefix_command
.c_str()) > 99)
1080 prefix_command
= "99"; // Let's not go overboard here.
1083 int enabler_inputst::prefix_end() {
1084 if (prefix_command
.size()) {
1085 int repeats
= atoi(prefix_command
.c_str());
1093 string
enabler_inputst::prefix() {
1094 return prefix_command
;