spring/spring — pull request #90 by MajBoredom (2013-12-20 16:13:27+00:00)
Title: Key modes -- lets users bind actions to sequences of keystrokes, and fixes a bug with the "unbind" command.

-------
This commit adds "key mode" functionality to spring 95.

A key mode is a keyboard state that is temporarily activated when you press a key.
Once it is active, other key bindings become temporarily available. This allows you
to create sequences (e.g. usually of just 2 or 3 keys) which have a unique meaning,
and it greatly expands the number of keyboard controls that can be bound to commands.

Example
-------
Using key modes you can have hotkey sequences such as:

ctrl+e,ctrl+e -> select all aircraft
ctrl+e,ctrl+r -> select all builders
ctrl+e,ctrl+t -> select all buildings
ctrl+e,ctrl+a -> select everything

To make this work, edit uikeys.txt with the text:

unbind ctrl+e
bind ctrl+e @selmode
bind @selmode+ctrl+e select AllMap+_Aircraft+_ClearSelection_SelectAll+
bind @selmode+ctrl+r select AllMap+_Builder+_ClearSelection_SelectAll+
bind @selmode+ctrl+t select AllMap+_Building+_ClearSelection_SelectAll+
bind @selmode+ctrl+a select AllMap++_ClearSelection_SelectAll+

Explanation
-----------
In the second line, we bind ctrl+e to a mode called "selmode". This text is arbitrary -- you can
call the mode anything you like as long as it is prefixed by the symbol '@'.

In the subsequent lines, we can treat "@selmode" as a modifier just like shift, alt, or ctrl.
In these lines, the key sequence that follows is only active when "selmode" is activated.
The requirement is that the mode modifier "@selmode" has to come at the start of the key sequence.

This is the Wrong Way:
bind ctrl+@selmode+a select AllMap++_ClearSelection_SelectAll+
..this will not work.

You should not try to bind the same key to multiple actions if one of the actions is a key mode activation.
For example, the following is allowed in uikeys.txt, but will not work:

bind ctrl+e say I want this action to occur
bind ctrl+e @selmode

Here, the key mode activation will be "hidden" by the first binding. They will not "cycle" as you may
be used to seeing with most mods. ***A key mode must be the only _action_ bound to a key or key sequence.***

However, you can chain together multiple modes to create 3-step, 4-step, or longer length sequences.
For example,

bind ctrl+e @modestep1
bind @modestep1+ctrl+e @modestep2
bind @modestep2+ctrl+s say Hello!

This defines a sequence
ctrl+e,ctrl+e,ctrl+s -> say "Hello!"

The possibilities are endless! Note that the suffix sequence ctrl+e,ctrl+s might still do nothing by itself.

Configuration setting in springsettings.cfg
-------------------------------------------
Finally, you can control how long a keyboard mode lasts before the default keybindings
are reset. Any key mode that is activated will be deactivated and the default keybindings
restored after this delay. This means that if you hit the first key and want to abort,
you can simply wait out the delay and the default bindings will be restored.
The configuration setting is KeyModeResetTime and is measured in milliseconds. The default
value is 400 -- this has been found to be "comfortable". If you are a very twitchy player
and can hit key combinations fast, you may like to try 200-300 or so. Remember that you
need to hit the second (and subsequent) keys in the combination before the reset time expires
or those keys will get sent to the default binding rather than the named key mode binding.
There is also a configuration setting called KeyModeSustain. If this is set to true, the current
key mode will be sustained after a key that uses it has been pushed. This lets you re-use
the same mode for multiple subsequent keystrokes if those subsequent keys share the same mode.
Setting this value to false will mean the that default key bindings are re-activated immediately
after you use a key that is bound into a particular mode.

Enjoy,
-MajBoredom

- fixed unbind so that it will accept only one parameter, the key sequence
- unchanged a lexical modification that occurred in the last commit
- added a new boolean configuration parameter KeyModeSustain