private static void LoadSequenceString(string line) { // Only bother with sequences that start with <Multi_key> var m1 = Regex.Match(line, @"^\s*<Multi_key>\s*([^:]*):[^""]*""(([^""]|\\"")*)""[^#]*#?\s*(.*)"); // ^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^ // keys result desc if (m1.Groups.Count < 4) { return; } var keysyms = Regex.Split(m1.Groups[1].Captures[0].ToString(), @"[\s<>]+"); if (keysyms.Length < 4) // We need 2 empty strings + at least 2 keysyms { return; } KeySequence seq = new KeySequence(); for (int i = 1; i < keysyms.Length; ++i) { if (keysyms[i] == String.Empty) { continue; } Key k = Key.FromKeySym(keysyms[i]); if (k == null) { //Console.WriteLine("Unknown key name <{0}>, ignoring sequence", keysyms[i]); return; // Unknown key name! Better bail out } seq.Add(k); } string result = m1.Groups[2].Captures[0].ToString(); string description = m1.Groups.Count >= 5 ? m1.Groups[4].Captures[0].ToString() : ""; // Replace \\ and \" in the string output result = new Regex(@"\\(\\|"")").Replace(result, "$1"); // Try to translate the description if appropriate int utf32 = StringToCodepoint(result); if (utf32 >= 0) { string key = String.Format("U{0:X04}", utf32); string alt_desc = unicode.Char.ResourceManager.GetString(key); if (alt_desc != null && alt_desc.Length > 0) { description = alt_desc; } } m_sequences.Add(seq, result, utf32, description); ++m_sequence_count; }
KeySequence UnicodeKeySequence(string keys) { var keySequence = new KeySequence(); foreach (var ch in keys) { keySequence.Add(Key.FromKeySym(Convert.ToString(ch))); } return(keySequence); }
private static void LoadSequenceString(string line) { // If this is an include directive, use LoadSequenceFile() again var m0 = Regex.Match(line, @"^\s*include\s*""([^""]*)"""); if (m0.Groups.Count > 1) { string file = m0.Groups[1].Captures[0].ToString(); // We support %H (user directory) but not %L (locale-specific dir) if (file.Contains("%L")) { return; } file = file.Replace("%H", GetUserDir()); // Also if path is not absolute, prepend user directory if (!Path.IsPathRooted(file)) { file = Path.Combine(GetUserDir(), file); } LoadSequenceFile(file); return; } // Only bother with sequences that start with <Multi_key> var m1 = Regex.Match(line, @"^\s*<Multi_key>\s*([^:]*):[^""]*""(([^""]|\\"")*)""[^#]*#?\s*(.*)"); // ^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^ // keys result desc if (m1.Groups.Count < 4) { return; } var keysyms = Regex.Split(m1.Groups[1].Captures[0].ToString(), @"[\s<>]+"); if (keysyms.Length < 4) // We need 2 empty strings + at least 2 keysyms { return; } KeySequence seq = new KeySequence(); for (int i = 1; i < keysyms.Length; ++i) { if (keysyms[i] == String.Empty) { continue; } Key k = Key.FromKeySym(keysyms[i]); if (k == null) { //Console.WriteLine("Unknown key name <{0}>, ignoring sequence", keysyms[i]); return; // Unknown key name! Better bail out } seq.Add(k); } string result = m1.Groups[2].Captures[0].ToString(); string description = m1.Groups.Count >= 5 ? m1.Groups[4].Captures[0].ToString() : ""; // Unescape \n \\ \" and more in the string output result = Regex.Replace(result, @"\\.", m => { switch (m.Value) { // These sequences are converted to their known value case @"\n": return("\n"); case @"\r": return("\r"); case @"\t": return("\t"); // For all other sequences, just strip the leading \ default: return(m.Value.Substring(1).ToString()); } }); // Try to translate the description if appropriate int utf32 = StringToCodepoint(result); if (utf32 >= 0) { string key = String.Format("U{0:X04}", utf32); string alt_desc = unicode.Char.ResourceManager.GetString(key); if (alt_desc != null && alt_desc.Length > 0) { description = alt_desc; } } m_sequences.Add(seq, result, utf32, description); ++m_sequence_count; }
private void ParseRule(string line) { // If this is an include directive, use LoadFile() again Match m0 = m_r0.Match(line); if (m0.Success) { string file = m0.Groups[1].Captures[0].Value; // We support %H (user directory) but not %L (locale-specific dir) if (file.Contains("%L")) { return; } file = file.Replace("%H", Settings.GetUserDir()); // Also if path is not absolute, prepend user directory if (!Path.IsPathRooted(file)) { file = Path.Combine(Settings.GetUserDir(), file); } // Prevent against include recursion if (!m_loaded_files.Contains(file)) { LoadFile(file); } return; } var m1 = m_r1.Match(line); if (!m1.Success) { return; } KeySequence seq = new KeySequence(); var keysyms = m_r2.Split(m1.Groups[1].Captures[0].Value); for (int i = 1; i < keysyms.Length - 1; ++i) { Key k = Key.FromKeySym(keysyms[i]); if (k == null) { if (!m_invalid_keys.ContainsKey(keysyms[i])) { m_invalid_keys[keysyms[i]] = true; Log.Debug($"Unknown key name <{keysyms[i]}>, ignoring sequence"); } return; // Unknown key name! Better bail out } seq.Add(k); } // Only bother with sequences of length >= 3 that start with <Multi_key> if (seq.Count < 3 || seq[0].VirtualKey != VK.COMPOSE) { return; } string result = m1.Groups[2].Captures[0].Value; string description = m1.Groups.Count >= 5 ? m1.Groups[4].Captures[0].Value : ""; // Unescape \n \\ \" and more in the string output result = Regex.Replace(result, @"\\.", m => { switch (m.Value) { // These sequences are converted to their known value case @"\n": return("\n"); case @"\r": return("\r"); case @"\t": return("\t"); // For all other sequences, just strip the leading \ default: return(m.Value.Substring(1)); } }); // Try to translate the description if appropriate int utf32 = StringToCodepoint(result); if (utf32 >= 0) { string key = $"U{utf32:X04}"; string alt_desc = unicode.Char.ResourceManager.GetString(key); if (!string.IsNullOrEmpty(alt_desc)) { description = alt_desc; } } // HACK: remove the first key (Multi_key) for now, because the // rest of the code cannot handle it. seq.RemoveAt(0); InsertSequence(seq, result, utf32, description); ++Count; }