예제 #1
0
 /// <summary>
 /// - Processes a character event into an Action that occurs while in the DcsParam state.
 ///   Events in this state will:
 ///   1. Ignore C0 control characters
 ///   2. Ignore Delete characters
 ///   3. Collect DCS parameter data
 ///   4. Enter DcsIntermediate if we see an intermediate
 ///   5. Begin to ignore all remaining parameters when an invalid character is detected (DcsIgnore)
 ///   6. Dispatch the Final character in preparation for parsing the data string
 /// </summary>
 /// <param name="ch"></param>
 private void EventDCSParam(byte ch)
 {
     if (ASCIIChars.IsC0Code(ch))
     {
         this.ActionIgnore(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.EnterDCSIntermediate();
     }
     else if (ASCIIChars.IsParameterInvalid(ch))
     {
         this.EnterDCSIgnore();
     }
     else
     {
         this.ActionDCSDispatch(ch);
     }
 }
예제 #2
0
        /// <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();
                }
            }
        }
예제 #3
0
 /// <summary>
 /// - Processes a character event into an Action that occurs while in the CsiEntry 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. Collect Control Sequence Private markers
 ///   7. Dispatch a control sequence with parameters for action
 /// </summary>
 /// <param name="ch"></param>
 private void EventCSIEntry(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.EnterCSIIntermediate();
     }
     else if (ASCIIChars.IsCSIInvalid(ch))
     {
         this.EnterCSIIgnore();
     }
     else if (ASCIIChars.IsNumericParamValue(ch) || ASCIIChars.IsParameterDelimiter(ch))
     {
         this.ActionParam(ch);
         this.EnterCSIParam();
     }
     else if (ASCIIChars.IsCSIPrivateMarker(ch))
     {
         this.ActionCollect(ch);
         this.EnterCSIParam();
     }
     else
     {
         this.ActionCSIDispatch(ch);
         this.EnterGround();
     }
 }
예제 #4
0
 /// <summary>
 /// - Processes a character event into a Action that occurs while in the OscParam state.
 ///   Events in this state will:
 ///   1. Trigger the OSC action associated with the param on an OscTerminator
 ///   2. If we see a ESC, enter the OscTermination state. We'll wait for one
 ///      more character before we dispatch the string.
 ///   3. Ignore OscInvalid characters.
 ///   4. Collect everything else into the OscString
 /// </summary>
 /// <param name="ch"></param>
 private void EventOSCString(byte ch)
 {
     if (ASCIIChars.IsOSCTerminator(ch))
     {
         // 出现了OSC结束符,那么进入Ground状态
         this.ActionOSCDispatch(ch);
         this.EnterGround();
     }
     else if (ASCIIChars.IsEscape(ch))
     {
         // OSC状态下出现了ESC字符,那么有两种情况会出现:
         // 1. ESC后面有ST字符,说明是OSC状态结束了
         // 2. ESC后面没有ST字符,说明是ESC状态
         // 所以这里定义一个OSCTermination状态来处理这两种状态
         this.EnterOSCTermination();
     }
     else if (ASCIIChars.IsOSCIndicator(ch))
     {
         // OSC非法字符,忽略
         this.ActionIgnore(ch);
     }
     else
     {
         // 剩下的就是OSC的有效字符,收集
         this.oscString.Append((char)ch);
     }
 }
예제 #5
0
 /// <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();
     }
 }
예제 #6
0
 /// <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();
     }
 }
예제 #7
0
 /// <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);
     }
 }
예제 #8
0
 /// <summary>
 /// - Handle the two-character termination of a OSC sequence.
 ///   Events in this state will:
 ///   1. Trigger the OSC action associated with the param on an OscTerminator
 ///   2. Otherwise treat this as a normal escape character event.
 /// </summary>
 /// <param name="ch"></param>
 private void EventOSCTermination(byte ch)
 {
     if (ASCIIChars.IsStringTermination(ch))
     {
         // OSC状态下出现了ESC后,后面紧跟着ST字符,说明是OSC状态结束了
         this.ActionOSCDispatch(ch);
         this.EnterGround();
     }
     else
     {
         // OSC状态下出现了ESC后,后面没有ST字符,说明要Cancel OSC状态并直接进入ESC模式
         this.EnterEscape();
         this.EventEscape(ch);
     }
 }
예제 #9
0
        /// <summary>
        /// 收集CSI状态下的Parameter字符
        ///  - Triggers the Param action to indicate that the state machine should store this character as a part of a parameter
        ///   to a control sequence.
        /// </summary>
        /// <param name="ch"></param>
        private void ActionParam(byte ch)
        {
            if (this.parameters.Count == 0)
            {
                this.parameters.Add(0);
            }

            if (ASCIIChars.IsParameterDelimiter(ch))
            {
                this.parameters.Add(0);
            }
            else
            {
                int last = this.parameters.Last();
                this.parameters[this.parameters.Count - 1] = this.AccumulateTo(ch, last);
            }
        }
예제 #10
0
 /// <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);
     }
 }
예제 #11
0
 /// <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();
     }
 }
예제 #12
0
 /// <summary>
 /// 进入到了OSC状态,开始解析OSC命令
 /// </summary>
 /// <param name="ch"></param>
 private void EventOSCParam(byte ch)
 {
     if (ASCIIChars.IsOSCTerminator(ch))
     {
         // OSC状态下出现了BEL结束符
         // 参考terminal的做法,进入Ground状态
         this.EnterGround();
     }
     else if (ASCIIChars.IsNumericParamValue(ch))
     {
         // OSC状态下的数字,收集起来
         this.ActionOSCParam(ch);
     }
     else if (ASCIIChars.IsOSCDelimiter(ch))
     {
         // OSC状态下出现了分隔符,说明要开始收集字符串了
         this.EnterOSCString();
     }
     else
     {
         // 其他所有的字符都忽略
         this.ActionIgnore(ch);
     }
 }
예제 #13
0
        /// <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();
                }
            }
        }
예제 #14
0
        /// <summary>
        /// 解析终端字节流
        /// </summary>
        /// <param name="bytes">要解析的字节流</param>
        public void ProcessCharacters(byte[] bytes)
        {
            int length = bytes.Length;

            for (int i = 0; i < length; i++)
            {
                byte ch = bytes[i];

                // 在OSCString的状态下,ESC转义字符可以用作OSC状态的结束符,所以在这里不进入ESC状态
                if (ASCIIChars.IsEscape(ch) && this.state != VTStates.OSCString)
                {
                    this.EnterEscape();
                }
                else
                {
                    switch (this.state)
                    {
                    case VTStates.Ground:
                    {
                        this.EventGround(ch);
                        break;
                    }

                    case VTStates.Escape:
                    {
                        this.EventEscape(ch);
                        break;
                    }

                    case VTStates.EscapeIntermediate:
                    {
                        this.EventEscapeIntermediate(ch);
                        break;
                    }

                    case VTStates.OSCParam:
                    {
                        this.EventOSCParam(ch);
                        break;
                    }

                    case VTStates.OSCString:
                    {
                        this.EventOSCString(ch);
                        break;
                    }

                    case VTStates.OSCTermination:
                    {
                        this.EventOSCTermination(ch);
                        break;
                    }

                    case VTStates.CSIEntry:
                    {
                        this.EventCSIEntry(ch);
                        break;
                    }

                    case VTStates.CSIIntermediate:
                    {
                        this.EventCSIIntermediate(ch);
                        break;
                    }

                    case VTStates.CSIIgnore:
                    {
                        this.EventCSIIgnore(ch);
                        break;
                    }

                    case VTStates.CSIParam:
                    {
                        this.EventCSIParam(ch);
                        break;
                    }

                    case VTStates.DCSEntry:
                    {
                        this.EventDCSEntry(ch);
                        break;
                    }

                    case VTStates.DCSIgnore:
                    {
                        this.EventDCSIgnore(ch);
                        break;
                    }

                    case VTStates.DCSIntermediate:
                    {
                        this.EventDCSIntermediate(ch);
                        break;
                    }

                    case VTStates.DCSParam:
                    {
                        this.EventDCSParam(ch);
                        break;
                    }

                    case VTStates.DCSPassthrough:
                    {
                        this.EventDCSPassThrough(ch);
                        break;
                    }

                    case VTStates.Vt52Param:
                    {
                        this.EventVt52Param(ch);
                        break;
                    }
                    }
                }
            }
        }