/// <summary> /// Add a key to the sequence currently being built. If necessary, output /// the finished sequence or trigger actions for invalid sequences. /// </summary> private static bool AddToSequence(Key key) { KeySequence old_sequence = new KeySequence(m_sequence); m_sequence.Add(key); // We try the following, in this order: // 1. if m_sequence + key is a valid sequence, we don't go further, // we append key to m_sequence and output the result. // 2. if m_sequence + key is a valid prefix, it means the user // could type other characters to build a longer sequence, // so just append key to m_sequence. // 3. if m_sequence + key is a valid generic prefix, continue as well. // 4. if m_sequence + key is a valid sequence, send it. // 5. (optionally) try again 1. and 2. ignoring case. // 6. none of the characters make sense, output all of them as if // the user didn't press Compose. foreach (bool ignore_case in Settings.CaseInsensitive.Value ? new bool[] { false, true } : new bool[] { false }) { if (Settings.IsValidSequence(m_sequence, ignore_case)) { string tosend = Settings.GetSequenceResult(m_sequence, ignore_case); Stats.AddSequence(m_sequence); Log.Debug("Valid sequence! Sending {0}", tosend); ResetSequence(); SendString(tosend); return(true); } if (Settings.IsValidPrefix(m_sequence, ignore_case)) { // Still a valid prefix, continue building sequence return(true); } if (!ignore_case) { if (Settings.IsValidGenericPrefix(m_sequence)) { return(true); } if (Settings.IsValidGenericSequence(m_sequence)) { string tosend = Settings.GetGenericSequenceResult(m_sequence); Stats.AddSequence(m_sequence); Log.Debug("Valid generic sequence! Sending {0}", tosend); ResetSequence(); SendString(tosend); return(true); } } // Try to swap characters if the corresponding option is set if (m_sequence.Count == 2 && Settings.SwapOnInvalid.Value) { var other_sequence = new KeySequence() { m_sequence[1], m_sequence[0] }; if (Settings.IsValidSequence(other_sequence, ignore_case)) { string tosend = Settings.GetSequenceResult(other_sequence, ignore_case); Stats.AddSequence(other_sequence); Log.Debug("Found swapped sequence! Sending {0}", tosend); ResetSequence(); SendString(tosend); return(true); } } } // Unknown characters for sequence, print them if necessary if (!Settings.DiscardOnInvalid.Value) { foreach (Key k in m_sequence) { // FIXME: what if the key is e.g. left arrow? if (k.IsPrintable) { SendString(k.ToString()); } } } if (Settings.BeepOnInvalid.Value) { SystemSounds.Beep.Play(); } ResetSequence(); return(true); }
/// <summary> /// Add a key to the sequence currently being built. If necessary, output /// the finished sequence or trigger actions for invalid sequences. /// </summary> private static bool AddToSequence(Key key) { KeySequence old_sequence = new KeySequence(m_sequence); m_sequence.Add(key); // We try the following, in this order: // 1. if m_sequence + key is a valid sequence, we don't go further, // we append key to m_sequence and output the result. // 2. if m_sequence + key is a valid prefix, it means the user // could type other characters to build a longer sequence, // so just append key to m_sequence. // 3. if m_sequence + key is a valid generic prefix, continue as well. // 4. if m_sequence + key is a valid sequence, send it. // 5. (optionally) try again 1. and 2. ignoring case. // 6. none of the characters make sense, output all of them as if // the user didn't press Compose. foreach (bool ignore_case in Settings.CaseInsensitive.Value ? new bool[] { false, true } : new bool[] { false }) { if (Settings.IsValidSequence(m_sequence, ignore_case)) { string tosend = Settings.GetSequenceResult(m_sequence, ignore_case); SendString(tosend); Log.Debug("Valid sequence! Sent “{0}”", tosend); Stats.AddSequence(m_sequence); ResetSequence(); return(true); } if (Settings.IsValidPrefix(m_sequence, ignore_case)) { // Still a valid prefix, continue building sequence return(true); } if (!ignore_case) { if (Settings.IsValidGenericPrefix(m_sequence)) { return(true); } if (Settings.GetGenericSequenceResult(m_sequence, out var tosend)) { SendString(tosend); Log.Debug("Valid generic sequence! Sent “{0}”", tosend); Stats.AddSequence(m_sequence); ResetSequence(); return(true); } } // Wait for a second character if SwapOnInvalid is true if (m_sequence.Count == 1 && Settings.SwapOnInvalid.Value) { return(true); } // Try to swap characters if the corresponding option is set if (m_sequence.Count == 2 && Settings.SwapOnInvalid.Value) { var other_sequence = new KeySequence() { m_sequence[1], m_sequence[0] }; if (Settings.IsValidSequence(other_sequence, ignore_case)) { string tosend = Settings.GetSequenceResult(other_sequence, ignore_case); SendString(tosend); Log.Debug("Found swapped sequence! Sent “{0}”", tosend); Stats.AddSequence(other_sequence); ResetSequence(); return(true); } } } // FIXME: At this point we know the key can’t be part of a valid // sequence, but this should not be a hard error if the key is a // modifier key. OnInvalidSequence(); return(true); }