1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Ensures final thing in a key sequence is fully typed; adds ability to quicken input.

This commit is contained in:
Thomas Harte 2020-02-29 18:12:32 -05:00
parent bd45c1c963
commit 4594a3c02b
4 changed files with 54 additions and 15 deletions

View File

@ -150,3 +150,7 @@ uint16_t *CharacterMapper::sequence_for_character(char character) {
return table_lookup_sequence_for_character(key_sequences, sizeof(key_sequences), character);
}
bool CharacterMapper::needs_pause_after_key(uint16_t key) {
return key != KeyControl && key != KeyShift;
}

View File

@ -38,7 +38,10 @@ struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {
};
struct CharacterMapper: public ::Utility::CharacterMapper {
uint16_t *sequence_for_character(char character);
uint16_t *sequence_for_character(char character) override;
bool needs_pause_after_reset_all_keys() override { return false; }
bool needs_pause_after_key(uint16_t key) override;
};
};

View File

@ -74,31 +74,51 @@ const uint16_t *Typer::sequence_for_character(char c) const {
return sequence;
}
bool Typer::try_type_next_character() {
uint16_t Typer::try_type_next_character() {
const uint16_t *const sequence = sequence_for_character(string_[string_pointer_]);
if(!sequence) {
return false;
return 0;
}
if(!phase_) delegate_->clear_all_keys();
else {
delegate_->set_key_state(sequence[phase_ - 1], true);
return sequence[phase_] != KeyboardMachine::MappedMachine::KeyEndSequence;
// If this is the start of the output sequence, start with a reset all keys.
// Then pause unless the caracter mapper says not to.
if(!phase_) {
delegate_->clear_all_keys();
if(character_mapper_->needs_pause_after_reset_all_keys()) {
return 0xffff; // Arbitrarily. Anything non-zero will do.
}
}
return true;
// Advance phase.
++phase_;
// If the sequence is over, stop.
if(sequence[phase_ - 1] == KeyboardMachine::MappedMachine::KeyEndSequence) {
return 0;
}
// Otherwise, type the key.
delegate_->set_key_state(sequence[phase_ - 1], true);
return sequence[phase_ - 1];
}
bool Typer::type_next_character() {
if(string_pointer_ == string_.size()) return false;
if(!try_type_next_character()) {
phase_ = 0;
++string_pointer_;
if(string_pointer_ == string_.size()) return false;
} else {
++phase_;
while(true) {
const uint16_t key_pressed = try_type_next_character();
if(!key_pressed) {
phase_ = 0;
++string_pointer_;
if(string_pointer_ == string_.size()) return false;
}
if(character_mapper_->needs_pause_after_key(key_pressed)) {
break;
}
}
return true;

View File

@ -28,6 +28,18 @@ class CharacterMapper {
/// @returns The EndSequence-terminated sequence of keys that would cause @c character to be typed.
virtual uint16_t *sequence_for_character(char character) = 0;
/// The typer will automatically reset all keys in between each sequence that it types.
/// By default it will pause for one key's duration when doing so. Character mappers
/// can eliminate that pause by overriding this method.
/// @returns @c true if the typer should pause after performing a reset; @c false otherwise.
virtual bool needs_pause_after_reset_all_keys() { return true; }
/// The typer will pause between every entry in a keyboard sequence. On some machines
/// that may not be necessary — it'll often depends on whether the machine needs time to
/// observe a modifier like shift before it sees the actual keypress.
/// @returns @c true if the typer should pause after forwarding @c key; @c false otherwise.
virtual bool needs_pause_after_key(uint16_t key) { return true; }
protected:
typedef uint16_t KeySequence[16];
@ -81,7 +93,7 @@ class Typer {
Delegate *delegate_;
std::unique_ptr<CharacterMapper> character_mapper_;
bool try_type_next_character();
uint16_t try_type_next_character();
const uint16_t *sequence_for_character(char) const;
};