/// <summary> /// - Processes a character event into an Action that occurs while in the DcsEntry state. /// Events in this state will: /// 1. Ignore C0 control characters /// 2. Ignore Delete characters /// 3. Begin to ignore all remaining characters when an invalid character is detected (DcsIgnore) /// 4. Store parameter data /// 5. Collect Intermediate characters /// 6. Dispatch the Final character in preparation for parsing the data string /// DCS sequences are structurally almost the same as CSI sequences, just with an /// extra data string. It's safe to reuse CSI functions for /// determining if a character is a parameter, delimiter, or invalid. /// </summary> /// <param name="ch"></param> private void EventDCSEntry(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsCSIInvalid(ch)) { this.EnterDCSIgnore(); } else if (ASCIIChars.IsNumericParamValue(ch) || ASCIIChars.IsParameterDelimiter(ch)) { this.ActionParam(ch); this.EnterDCSParam(); } else if (ASCIIChars.IsIntermediate(ch)) { this.ActionCollect(ch); this.EnterDCSIntermediate(); } else { this.ActionDCSDispatch(ch); } }
/// <summary> /// - Processes a character event into an Action that occurs while in the EscapeIntermediate state. /// Events in this state will: /// 1. Execute C0 control characters /// 2. Ignore Delete characters /// 3. Collect Intermediate characters /// 4. Dispatch an Escape action. /// </summary> /// <param name="ch"></param> private void EventEscapeIntermediate(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionExecute(ch); } else if (ASCIIChars.IsIntermediate(ch)) { this.ActionCollect(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else if (this.isAnsiMode) { this.ActionEscDispatch(ch); this.EnterGround(); } else if (ASCIIChars.IsVt52CursorAddress(ch)) { this.EnterVt52Param(); } else { this.ActionVt52EscDispatch(ch); this.EnterGround(); } }
/// <summary> /// - Processes a character event into an Action that occurs while in the CsiParam state. /// Events in this state will: /// 1. Execute C0 control characters /// 2. Ignore Delete characters /// 3. Collect Intermediate characters /// 4. Begin to ignore all remaining parameters when an invalid character is detected (CsiIgnore) /// 5. Store parameter data /// 6. Dispatch a control sequence with parameters for action /// </summary> /// <param name="ch"></param> private void EventCSIParam(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionExecute(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsNumericParamValue(ch) || ASCIIChars.IsParameterDelimiter(ch)) { this.ActionParam(ch); } else if (ASCIIChars.IsIntermediate(ch)) { this.ActionCollect(ch); this.EnterCSIIntermediate(); } else if (ASCIIChars.IsParameterInvalid(ch)) { this.EnterCSIIgnore(); } else { this.ActionCSIDispatch(ch); this.EnterGround(); } }
/// <summary> /// 当状态改变为Ground的时候触发 /// </summary> /// <param name="ch"></param> private void EventGround(byte ch) { if (ASCIIChars.IsC0Code(ch) || ASCIIChars.IsDelete(ch)) { // 如果是C0控制字符和Delete字符,说明要执行动作 this.ActionExecute(ch); } else if (ASCIIChars.IsPrintable(ch)) { // 其他字符直接打印 this.ActionPrint(ch); } else { // 不是可见字符,当多字节字符处理,用UTF8编码 // UTF8参考:https://www.cnblogs.com/fnlingnzb-learner/p/6163205.html if (this.unicodeText.Count == 0) { bool bit6 = BytesExtentions.GetBit(ch, 5); this.unicodeText.Capacity = bit6 ? 3 : 2; } this.unicodeText.Add(ch); if (this.unicodeText.Count == this.unicodeText.Capacity) { string text = Encoding.UTF8.GetString(this.unicodeText.ToArray()); this.ActionPrint(text); this.unicodeText.Clear(); } } }
/// <summary> /// 当状态变成Escape的时候触发 /// </summary> /// <param name="ch"></param> private void EventEscape(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionExecute(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsIntermediate(ch)) { this.ActionCollect(ch); this.EnterEscapeIntermediate(); } else if (this.isAnsiMode) { if (ASCIIChars.IsCSIIndicator(ch)) { // 0x5B,进入到了csi entry状态 this.EnterCSIEntry(); } else if (ASCIIChars.IsOSCIndicator(ch)) { // 0x5D,进入到了osc状态 this.EnterOSCParam(); } else if (ASCIIChars.IsDCSIndicator(ch)) { // 0x50,进入到了dcs状态 this.EnterDCSEntry(); } else { this.ActionEscDispatch(ch); this.EnterGround(); } } else if (ASCIIChars.IsVt52CursorAddress(ch)) { // 判断是否是VT52模式下的移动光标指令, 当进入了VT52模式下才会触发 // 在VT52模式下只有移动光标的指令有参数,所以这里把移动光标的指令单独做处理 this.EnterVt52Param(); } else { // 这里是其他的不带参数的VT52控制字符 this.ActionVt52EscDispatch(ch); this.EnterGround(); } }
/// <summary> /// - Processes a character event into an Action that occurs while in the DcsPassThrough state. /// Events in this state will: /// 1. Pass through if character is valid. /// 2. Ignore everything else. /// The termination state is handled outside when an ESC is seen. /// </summary> /// <param name="ch"></param> private void EventDCSPassThrough(byte ch) { if (ASCIIChars.IsC0Code(ch) || ASCIIChars.IsDCSPassThroughValid(ch)) { if (!this.dcsStringHandler(ch)) { this.EnterDCSIgnore(); } } else { this.ActionIgnore(ch); } }
/// <summary> /// - Processes a character event into an Action that occurs while in the DcsIntermediate state. /// Events in this state will: /// 1. Ignore C0 control characters /// 2. Ignore Delete characters /// 3. Collect intermediate data. /// 4. Begin to ignore all remaining intermediates when an invalid character is detected (DcsIgnore) /// 5. Dispatch the Final character in preparation for parsing the data string /// </summary> /// <param name="ch"></param> private void EventDCSIntermediate(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsIntermediate(ch)) { this.ActionCollect(ch); } else if (ASCIIChars.IsIntermediateInvalid(ch)) { this.EnterDCSIgnore(); } else { this.ActionDCSDispatch(ch); } }
/// <summary> /// Processes a character event into an Action that occurs while in the CsiIgnore state. /// Events in this state will: /// 1. Execute C0 control characters /// 2. Ignore Delete characters /// 3. Collect Intermediate characters /// 4. Begin to ignore all remaining parameters when an invalid character is detected (CsiIgnore) /// 5. Return to Ground /// </summary> /// <param name="ch"></param> private void EventCSIIgnore(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionExecute(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsIntermediate(ch)) { this.ActionIgnore(ch); } else if (ASCIIChars.IsIntermediateInvalid(ch)) { this.ActionIgnore(ch); } else { this.EnterGround(); } }
/// <summary> /// - Processes a character event into an Action that occurs while in the Vt52Param state. /// Events in this state will: /// 1. Execute C0 control characters /// 2. Ignore Delete characters /// 3. Store exactly two parameter characters /// 4. Dispatch a control sequence with parameters for action (always Direct Cursor Address) /// </summary> /// <param name="ch"></param> private void EventVt52Param(byte ch) { if (ASCIIChars.IsC0Code(ch)) { this.ActionExecute(ch); } else if (ASCIIChars.IsDelete(ch)) { this.ActionIgnore(ch); } else { this.parameters.Add(ch); if (this.parameters.Count == 2) { // The command character is processed before the parameter values, // but it will always be 'Y', the Direct Cursor Address command. // 到了这里说明Y指令的参数收集完了,可以执行了,因为Y指令是移动光标指令,有且只有两个参数 this.ActionVt52EscDispatch((byte)'Y'); this.EnterGround(); } } }