/// <summary> /// Build automaton from word string /// </summary> /// <param name="word">Word string</param> /// <param name="keyboard">Keyboard</param> /// <returns>Automaton</returns> public virtual InputAutomaton ToAutomaton(string s, InputKeyboard keyboard) { // Start state InputAutomaton start = new InputAutomaton(); InputAutomaton current = start; string c; for (int i = 0; i < s.Length; i++) { InputAutomaton next; // Get next input character (Hiragana, Alphabet, Number, Sign) c = s.Substring(i, 1); // Convert the input character to Katakana, Large alphabet, Hankaku. // In old version, As SJIS does not have Hiragana of "ヴ", we converted that to Katakana c = c.Hira2Kana(); c = c.Zenkaku2Hankaku(); next = new InputAutomaton(); if (CreateAutomaton(current, c, next, InputCustomDefaultV1.Ope_NO_CUSTOM)) { current = next; } } return(start); }
/// <summary> /// Build automaton from word string /// </summary> /// <param name="word">Word string</param> /// <param name="keyboard">Keyboard</param> /// <returns>Automaton</returns> public virtual InputAutomaton ToAutomaton(string s, InputKeyboard keyboard) { var plane = GetPlane(keyboard, "Default"); // Start state InputAutomaton start = new InputAutomaton(); InputAutomaton current = start; string c; // Make automaton for (int i = 0; i < s.Length; i++) { InputAutomaton next; // Get next input character c = s.Substring(i, 1); next = new InputAutomaton(); current = ProcessNormal(plane, s, current, ref c, ref i, next); current = next; } return(start); }
/// <summary> /// Build automaton from word string /// </summary> /// <param name="word">Word string</param> /// <param name="keyboard">Keyboard</param> /// <returns>Automaton</returns> public virtual InputAutomaton ToAutomaton(string s, InputKeyboard keyboard) { // Start state InputAutomaton start = new InputAutomaton(); InputAutomaton current = start; string c, c_conv; var s_conv = s.Kana2Hira(); s_conv = s.Zenkaku2Hankaku(true, true); // Make automaton for (int i = 0; i < s.Length; i++) { InputAutomaton next; // Get next input character c = s.Substring(i, 1); c_conv = s_conv.Substring(i, 1); // Use original next = new InputAutomaton(); current.SetConnect(c_conv[0], new InputAutomaton.Connect() { Automaton = next, Flags = InputCustomDefaultV1.Ope_NO_CUSTOM, Character = c, }); current = next; } return(start); }
/// <summary> /// Process normal character /// </summary> /// <param name="plane">Plane</param> /// <param name="s">String</param> /// <param name="current">Current automaton</param> /// <param name="c">Char</param> /// <param name="index">Index</param> /// <param name="next">Next automaton</param> /// <returns></returns> internal InputAutomaton ProcessNormal(int plane, string s, InputAutomaton current, ref string c, ref int index, InputAutomaton next) { BitFlag custom = InputCustomDefaultV1.Ope_NO_CUSTOM; // Add automaton CreateAutomaton(plane, current, c, next, custom); return(current); }
/// <summary> /// Build string from automaton. /// </summary> /// <param name="root">Root state</param> /// <param name="current">Current State</param> /// <param name="inputCustom">Input custom (do not modify)</param> /// <param name="pos">Return current position</param> /// <param name="nextCharacter">Return next valid character.</param> /// <returns>If nextCharacter is -1, Return only next character, otherwise, return all the string.</returns> public virtual string FromAutomaton(InputAutomaton root, InputAutomaton current, IInputCustom custom, ref int pos, ref int nextCharacter) { var result = new StringBuilder(); pos = 0; InputAutomaton automaton = root; while (!(automaton.IsAccept())) { bool found = false; KeyValuePair <int, InputAutomaton.Connect> select = new KeyValuePair <int, InputAutomaton.Connect>(); foreach (var i in automaton.GetConnect()) { // Use first connection because no need to consider customization int c = i.Key; bool valid = false; InputAutomaton automaton_tmp = automaton.Input(c, ref valid, null); if (current == automaton_tmp) { select = i; found = true; } } if (!found) { // Found no route, use the first route select = automaton.GetConnect().First(); } int c2 = select.Key; string addstring = select.Value.Character; // In CPU mode, use only first key if (nextCharacter != -1) { nextCharacter = c2; break; } // Go to next automaton bool valid2 = false; result.Append(addstring); automaton = automaton.Input(c2, ref valid2, null); if (current == automaton) { pos = result.Length; } } return(result.ToString()); }
/// <summary> /// Build string from automaton. /// </summary> /// <param name="root">Root state</param> /// <param name="current">Current State</param> /// <param name="inputCustom">Input custom (do not modify)</param> /// <param name="pos">Return current position</param> /// <param name="nextCharacter">Return next valid character.</param> /// <returns>If nextCharacter is -1, Return only next character, otherwise, return all the string.</returns> public virtual string FromAutomaton(InputAutomaton root, InputAutomaton current, IInputCustom custom, ref int pos, ref int nextCharacter) { var result = new StringBuilder(); pos = 0; InputAutomaton automaton = root; while (!(automaton.IsAccept())) { int c = '\0'; string addstring = ""; // If we have perfect input custom, use that foreach (var i in automaton.GetConnect()) { if (custom.IsSet(i.Value.Flags)) { c = i.Key; addstring = i.Value.Character; break; } } if (c == '\0') { // Found no route, use the first route c = automaton.GetConnect().First().Key; addstring = automaton.GetConnect().First().Value.Character; } // In CPU mode, use only first key if (nextCharacter != -1) { nextCharacter = c; break; } // Go to next automaton bool valid = false; result.Append(addstring); automaton = automaton.Input(c, ref valid, null); if (current == automaton) { pos = result.Length; } } return(result.ToString()); }
/// <summary> /// Create new automaton /// </summary> /// <param name="current"></param> /// <param name="c"></param> /// <param name="next"></param> /// <param name="customAdd"></param> internal bool CreateAutomaton(InputAutomaton current, string c, InputAutomaton next, BitFlag customAdd) { // Previous automaton InputAutomaton prev = current; if (!_kanamap.ContainsKey(c)) { // Input is not supported return(false); } var kanamap = _kanamap[c]; if (VersionHelper.WTVersion == 404) { // There is a bug in the version 405 // To be compatible with that, we add ぱ/ぴ/ぺ with Shift Handakuten if ((_imAuthor == "Denasu System") && (_imName == "JISかな") && (c == "パ" || c == "ピ" || c == "ペ")) { kanamap = new List <KeyStroke>(); foreach (var j in _kanamap[c]) { kanamap.Add(j); if (j.Stroke.Count() == 2 && ((j.Stroke[0] & (int)WTKeyCode.Shift) != (int)WTKeyCode.Shift) && (j.Stroke[1] & (int)WTKeyCode.Shift) != (int)WTKeyCode.Shift) { kanamap.Add(new KeyStroke() { Custom = j.Custom, Input = j.Input, Stroke = new int[2] { j.Stroke[0] | (int)WTKeyCode.Shift, j.Stroke[1] | (int)WTKeyCode.Shift, } }); } } } } foreach (var j in kanamap) { if (j.Stroke.Count() == 0) { continue; } current = prev; // Create new automaton for each stroke for (var k = 0; k < j.Stroke.Count(); k++) { if (j.Stroke[k] == (int)WTKeyCode.NoKey) { continue; } if (k + 1 == j.Stroke.Count()) { // The last alphabet InputAutomaton.Connect connect = new InputAutomaton.Connect() { Automaton = next, Flags = j.Custom.Or(customAdd), Character = j.Input, }; current.SetConnect(j.Stroke[k], connect); current = next; } else { InputAutomaton.Connect connect = current.GetConnect(j.Stroke[k]); if (connect == null) { // Create a automaton with Flags connect = new InputAutomaton.Connect() { Automaton = new InputAutomaton(), Flags = j.Custom.Or(customAdd), Character = "", }; current.SetConnect(j.Stroke[k], connect); current = connect.Automaton; } else { // To make it deterministic, use existing automaton connect.Flags = connect.Flags.Or(j.Custom); current = connect.Automaton; } } } } return(true); }
/// <summary> /// Create new automaton /// </summary> /// <param name="plane">Plane</param> /// <param name="current">Current Automaton</param> /// <param name="c">char</param> /// <param name="next">Next Automaton</param> /// <param name="customAdd">Custom to add</param> internal void CreateAutomaton(int plane, InputAutomaton current, string c, InputAutomaton next, BitFlag customAdd) { // Previous automaton InputAutomaton prev = current; if (!_strokemap[plane].ContainsKey(c)) { // Input is not supported return; } // For all the stroke for c (e.g. "か"->ka, ca) foreach (var stroke in _strokemap[plane][c]) { if (stroke.Stroke.Count() == 0) { continue; } current = prev; // Create new automaton for each stroke for (var alphabet = 0; alphabet < stroke.Stroke.Count(); alphabet++) { if (stroke.Stroke[alphabet] == (int)WTKeyCode.NoKey) { // Unknown continue; } if (alphabet + 1 == stroke.Stroke.Count()) { // The last alphabet current.SetConnect(stroke.Stroke[alphabet], new InputAutomaton.Connect() { Automaton = next, Flags = stroke.Custom.Or(customAdd), Character = stroke.Input.Substring(alphabet, 1), }); current = next; } else { // Middle alphabet InputAutomaton.Connect connect = current.GetConnect(stroke.Stroke[alphabet]); if (connect == null) { // This automaton doesn't have the connection for this alphabet // Create a new connection for this alphabet connect = new InputAutomaton.Connect() { Automaton = new InputAutomaton(), Flags = stroke.Custom.Or(customAdd), Character = stroke.Input.Substring(alphabet, 1), }; // Connect current.SetConnect(stroke.Stroke[alphabet], connect); current = connect.Automaton; } else { // This automaton already have a connection for this alphabet // To make it deterministic, use existing automaton connect.Flags = connect.Flags.Or(stroke.Custom); current = connect.Automaton; } } } } }