/// <summary> /// Key input hander for this state /// </summary> /// <param name="keyCode">Key code</param> /// <param name="press">Key is pressed or not</param> /// <param name="result">Output of this state</param> /// <param name="currentTime">Current time</param> /// <returns>Next state</returns> public override State Handle(int keyCode, bool press, List <int> result, long currentTime) { if (press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { // Oyayubi Key pressed. Go to Oyayubi Key state. _lsOrRs = (keyCode == _lsKeyCode) ? _lsKeyCode : _rsKeyCode; _timeLsOrRsKey = currentTime; return(StateLsOrRs.Instance()); } else if (!press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { // Oyayubi Key released. Can ignore return(Instance()); } else if (press) { // Char Key pressed. Go to Char state. _keyCode = keyCode; _timeCharKey = currentTime; return(StateChar.Instance()); } else if (!press) { // Char Key released. Can ignore. return(Instance()); } // Unknown return(null); }
/// <summary> /// Get instance /// </summary> /// <returns>Instance</returns> public static State Instance() { if (_instance == null) { _instance = new StateChar(); } return(_instance); }
/// <summary> /// Key input hander for this state /// </summary> /// <param name="keyCode">Key code</param> /// <param name="press">Key is pressed or not</param> /// <param name="result">Output of this state</param> /// <param name="currentTime">Current time</param> /// <returns>Next state</returns> public override State Handle(int keyCode, bool press, List <int> result, long currentTime) { if (press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { if (keyCode == _lsOrRs) { // The same Oyayubi Key pressed. Can ignore return(StateLsOrRs.Instance()); } // Opposite Oyayubi Key pressed // No rule -> Update Oyayubi Key int oldOfs = keyCode; keyCode = _lsOrRs; _lsOrRs = (oldOfs == _lsKeyCode) ? _lsKeyCode : _rsKeyCode; _timeLsOrRsKey = currentTime; return(StateLsOrRs.Instance()); } else if (!press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { // Oyayubi Key released // Back to initial state keyCode = _lsOrRs; return(StateNone.Instance()); } else if (press) { // Char key pressed _timeCharKey = currentTime; _keyCode = keyCode; if (_timeCharKey - _timeLsOrRsKey > _threshold) { // Rule 1-1'. Oyayubi ON -> Timeout keyCode = _lsOrRs; // Go to Char Key state return(StateChar.Instance()); } // Rule 2-1. Oyayubi ON + Char ON -> Char with Oyayubi return(StateLsOrRsWithChar.Instance()); } else if (!press) { // Char Key released. Can ignore return(StateLsOrRs.Instance()); } // Unknown return(null); }
private Token GetChar() { StateChar state = StateChar.START; Char c = '\0'; Next(); var invalidChars = new HashSet <Char>("\'\n"); string escapeChars = @"abfnrtv'""\"; string correspondingEscapeChars = "\a\b\f\n\r\t\v\'\"\\"; Token result = null; int length = 0; while (true) { switch (state) { case StateChar.START: c = Next(); switch (c) { case '\\': state = StateChar.S; break; default: if (invalidChars.Contains(c)) { state = StateChar.FAILED; } else { state = StateChar.C; } break; } break; case StateChar.C: result = Token.GetCharToken(c, lexemeBegin, length + 2); c = Next(); if (c == '\'') { state = StateChar.FINISH; } else { state = StateChar.FAILED; } break; case StateChar.S: c = Next(); if (escapeChars.Contains(c)) { c = correspondingEscapeChars[escapeChars.IndexOf(c)]; state = StateChar.C; } else { state = StateChar.FAILED; } break; case StateChar.FINISH: return(result); case StateChar.FAILED: ErrorMessage.Add($"Character Parse failed when meeting '{c}'. "); return(Token.GetErrorToken(lexemeBegin, length + 1)); } length++; } }
/// <summary> /// Key input hander for this state /// </summary> /// <param name="keyCode">Key code</param> /// <param name="press">Key is pressed or not</param> /// <param name="result">Output of this state</param> /// <param name="currentTime">Current time</param> /// <returns>Next state</returns> public override State Handle(int keyCode, bool press, List <int> result, long currentTime) { if (press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { if (keyCode == _lsOrRs) { // The same Oyayubi Key pressed. Can ignore return(StateLsOrRsWithChar.Instance()); } // Opposite Oyayubi Key pressed // (Char Key with Oyayubi Key1) + (Oyayubi Key2) // Either of: // Rule 2-1. Oyayubi ON + Charl ON -> Char with Oyayubi // Rule 2-2. Char ON + Oyayubi ON -> Char with Oyayubi // Set Oyayubi Key flag to Char Key int oldOfs = keyCode; keyCode = _keyCode; keyCode |= (int)(_lsOrRs == _lsKeyCode ? WTKeyCode.Custom1 : WTKeyCode.Custom2); result.Add(keyCode); // Go to Oyayubi Key2 state _lsOrRs = (oldOfs == _lsKeyCode) ? _lsKeyCode : _rsKeyCode; _timeLsOrRsKey = currentTime; return(StateLsOrRs.Instance()); } else if (!press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { // Oyayubi Key released // Either of: // Rule 2-1. Oyayubi ON + Charl ON -> Char with Oyayubi // Rule 2-2. Char ON + Oyayubi ON -> Char with Oyayubi // Set Oyayubi Key flag to Char Key keyCode = _keyCode; keyCode |= (int)(_lsOrRs == _lsKeyCode ? WTKeyCode.Custom1 : WTKeyCode.Custom2); result.Add(keyCode); // Back to initial state return(StateNone.Instance()); } else if (press) { // Char Key pressed if (_timeLsOrRsKey < _timeCharKey) { // (Oyayubi Key with Char Key1) + (Char Key2) // Rule 2-1. Oyayubi ON + Charl ON -> Char with Oyayubi // Set Oyayubi Key flag to Char Key1 int tmp = keyCode; keyCode = _keyCode; keyCode |= (int)(_lsOrRs == _lsKeyCode ? WTKeyCode.Custom1 : WTKeyCode.Custom2); result.Add(keyCode); _timeCharKey = currentTime; _keyCode = tmp; // Go to Char Key2 state return(StateChar.Instance()); } else { long time = currentTime; if (time - _timeLsOrRsKey > _threshold) { // Rule 1-1'. Oyayubi ON -> Timeout (with Char Key2) // Set Oyayubi Key flag to Char Key1 int tmp = keyCode; keyCode = _keyCode; keyCode |= (int)(_lsOrRs == _lsKeyCode ? WTKeyCode.Custom1 : WTKeyCode.Custom2); result.Add(keyCode); _timeCharKey = currentTime; _keyCode = tmp; // Go to Char Key2 state return(StateChar.Instance()); } // Rule 3-1. Char1 ON + Oyayubi ON + Char2 ON // We have to determine which Char Key the Oyayubi Key is attached to. if (_timeLsOrRsKey - _timeCharKey <= time - _timeLsOrRsKey) { // Rule 3-1a. If (t(Oyayubi) - T(Char1)) <= (t(Char2) - T(Oyayubi)), Char1 with Oyayubi // Set Oyayubi Key flag to Char Key1 int tmp = keyCode; keyCode = _keyCode; keyCode |= (int)(_lsOrRs == _lsKeyCode ? WTKeyCode.Custom1 : WTKeyCode.Custom2); result.Add(keyCode); _timeCharKey = currentTime; _keyCode = tmp; // Go to Char Key2 state return(StateChar.Instance()); } else { // Rule 3-1b. If (t(Oyayubi) - T(Char1)) > (t(Char2) - T(Oyayubi)), Char2 with Oyayubi // Do not set Oyayubi Key flag to Char Key1 int tmp = keyCode; keyCode = _keyCode; result.Add(keyCode); // Go to Char Key2 with Oyayubi Key state _timeCharKey = time; _keyCode = tmp; return(StateLsOrRsWithChar.Instance()); } } } else if (!press) { // Char Key released if (keyCode != _keyCode) { // Unrelated Char released. Can ignore return(StateLsOrRsWithChar.Instance()); } // Either of: // Rule 2-1. Oyayubi ON + Charl ON -> Char with Oyayubi // Rule 2-2. Char ON + Oyayubi ON -> Char with Oyayubi // Set Oyayubi Key flag to Char Key keyCode = _keyCode; keyCode |= (int)(_lsOrRs == _lsKeyCode ? WTKeyCode.Custom1 : WTKeyCode.Custom2); result.Add(keyCode); // Back to initial state return(StateNone.Instance()); } // Unknown return(null); }
/// <summary> /// Key input hander for this state /// </summary> /// <param name="keyCode">Key code</param> /// <param name="press">Key is pressed or not</param> /// <param name="result">Output of this state</param> /// <param name="currentTime">Current time</param> /// <returns>Next state</returns> public override State Handle(int keyCode, bool press, List <int> result, long currentTime) { if (press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { // Oyayubi Key pressed. _timeLsOrRsKey = currentTime; if (_timeLsOrRsKey - _timeCharKey > _threshold) { // Rule 1-1. Char ON -> Timeout // Process Char Key int oldOfs = keyCode; keyCode = _keyCode; result.Add(keyCode); // Go to Oyayubi Key state _lsOrRs = (oldOfs == _lsKeyCode) ? _lsKeyCode : _rsKeyCode; _timeLsOrRsKey = currentTime; return(StateLsOrRs.Instance()); } // Rule 2-2. Char ON + Oyayubi ON -> Char with Oyayubi _lsOrRs = (keyCode == _lsKeyCode) ? _lsKeyCode : _rsKeyCode; return(StateLsOrRsWithChar.Instance()); } else if (!press && (keyCode == _rsKeyCode || keyCode == _lsKeyCode)) { // Oyayubi Key released. Can ignore return(StateChar.Instance()); } else if (press) { if (keyCode == _keyCode) { // The same Char Key pressed. Can ignore return(StateChar.Instance()); } // Rule 1-3. Char1 ON -> Char2 ON -> Char1 // Process Char Key1 int tmp = keyCode; keyCode = _keyCode; result.Add(keyCode); // Char Key2 pressed. Go to Char state. _timeCharKey = currentTime; _keyCode = tmp; return(StateChar.Instance()); } else if (!press) { if (keyCode != _keyCode) { // Unrelated Char released. Can ignore return(StateChar.Instance()); } // Rule 1-2. Char ON -> Char OFF -> Char // Process Char Key keyCode = _keyCode; result.Add(keyCode); // Back to initial state return(StateNone.Instance()); } // Unknown return(null); }
public void LoadSpec(string specStr) { AddAction(new State(0, '0'), new Action(0, '0', Direction.R)); int pos = 0, oldPos = 0; uint currState = 0; char currInput = '1'; string spec = specStr + "110"; // "110" removed for 'optimization', so // add it back while (pos < spec.Length) { var dir = Direction.Undef; int dirPos = 0x7FFFFFFF, matchLen = 0; // find first direction Match match = _stopRegex.Match(spec, pos); if (match.Success) { dir = Direction.Stop; dirPos = match.Index; matchLen = match.Length; } match = _leftRegex.Match(spec, pos); if (match.Success && match.Index < dirPos) { dir = Direction.L; dirPos = match.Index; matchLen = match.Length; } match = _rightRegex.Match(spec, pos); if (match.Success && match.Index < dirPos) { dir = Direction.R; dirPos = match.Index; matchLen = match.Length; } if (dir == Direction.Undef) { throw new SpecLoadException(spec.Substring(pos, 20)); } pos = dirPos; StateChar sc = GetStateAndChar(spec.Substring(oldPos, pos - oldPos)); var s = new State(currState, currInput); var a = new Action(sc.State, sc.C, dir); AddAction(s, a); pos += matchLen; oldPos = pos; currInput = (currInput == '0' ? '1' : '0'); if (currInput == '0') { currState++; } } _specLoaded = true; }