Example #1
0
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) into what the
        /// terminal wants to see.
        /// Subclasses of this should perform their own manipulations, then fallthrough
        /// to this base class implementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public override char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                case ExpectNextChar.RESIZEWIDTH:
                    pendingWidth   = t;
                    outputExpected = ExpectNextChar.RESIZEHEIGHT;
                    break;

                case ExpectNextChar.RESIZEHEIGHT:
                    int height = t;
                    sb.AppendFormat("{0}8;{1};{2}t", CSI, height, pendingWidth);
                    outputExpected = ExpectNextChar.NORMAL;
                    break;

                case ExpectNextChar.INTITLE:
                    if (t == (char)UnicodeCommand.TITLEEND)
                    {
                        sb.AppendFormat("{0}]2;{1}{2}", ESCAPE_CHARACTER, pendingTitle, BELL_CHAR);
                        pendingTitle   = new StringBuilder();
                        outputExpected = ExpectNextChar.NORMAL;
                    }
                    else
                    {
                        pendingTitle.Append(t);
                    }
                    break;

                default:
                    switch (t)
                    {
                    case (char)UnicodeCommand.RESIZESCREEN:
                        outputExpected = ExpectNextChar.RESIZEWIDTH;
                        break;

                    case (char)UnicodeCommand.TITLEBEGIN:
                        outputExpected = ExpectNextChar.INTITLE;
                        pendingTitle   = new StringBuilder();
                        break;

                    case (char)UnicodeCommand.CLEARSCREEN:
                        sb.AppendFormat("{0}?47h", ESCAPE_CHARACTER); // <-- Tells xterm to use fixed-buffer mode, not saving in scrollback.
                        sb.AppendFormat("{0}2J{0}H", CSI);            // <-- The normal clear screen char from vt100.
                        break;

                    default:
                        sb.Append(t);         // default passhtrough
                        break;
                    }
                    break;
                }
            }
            return(base.OutputConvert(sb.ToString()));
        }
Example #2
0
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) into what the
        /// terminal wants to see.
        /// Subclasses of this should perform their own manipulations, then fallthrough
        /// to this base class implementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public override char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                    case ExpectNextChar.RESIZEWIDTH:
                        pendingWidth = t;
                        outputExpected = ExpectNextChar.RESIZEHEIGHT;
                        break;
                    case ExpectNextChar.RESIZEHEIGHT:
                        int height = t;
                        sb.AppendFormat("{0}8;{1};{2}t", CSI, height, pendingWidth);
                        outputExpected = ExpectNextChar.NORMAL;
                        break;
                    case ExpectNextChar.INTITLE:
                        if (t == (char)UnicodeCommand.TITLEEND)
                        {

                            sb.AppendFormat("{0}]2;{1}{2}", ESCAPE_CHARACTER , pendingTitle, BELL_CHAR);
                            pendingTitle = new StringBuilder();
                            outputExpected = ExpectNextChar.NORMAL;
                        }
                        else
                            pendingTitle.Append(t);
                        break;
                    default:
                        switch (t)
                        {
                            case (char)UnicodeCommand.RESIZESCREEN:
                                outputExpected = ExpectNextChar.RESIZEWIDTH;
                                break;
                            case (char)UnicodeCommand.TITLEBEGIN:
                                outputExpected = ExpectNextChar.INTITLE;
                                pendingTitle = new StringBuilder();
                                break;
                            case (char)UnicodeCommand.CLEARSCREEN:
                                sb.AppendFormat("{0}?47h", ESCAPE_CHARACTER);                   // <-- Tells xterm to use fixed-buffer mode, not saving in scrollback.
                                sb.AppendFormat("{0}2J{0}H", CSI);  // <-- The normal clear screen char from vt100.
                                break;
                            default: 
                                sb.Append(t); // default passhtrough
                                break;
                        }
                        break;
                }
            }
            return base.OutputConvert(sb.ToString());
        }
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) into what the terminal
        /// wants to see.
        /// In this base class, all it does is just mostly passthru things as-is with no
        /// conversions.
        /// Subclasses of this should perform their own manipulations, then fallthrough
        /// to this base class inmplementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public virtual char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                case ExpectNextChar.RESIZEWIDTH:
                    pendingWidth   = t;
                    outputExpected = ExpectNextChar.RESIZEHEIGHT;
                    break;

                case ExpectNextChar.RESIZEHEIGHT:
                    int height = t;
                    sb.Append("{Please resize to " + pendingWidth + "x" + height + "}");     // By default, assume the terminal has no such control code, but this can be overridden.
                    outputExpected = ExpectNextChar.NORMAL;
                    break;

                case ExpectNextChar.INTITLE:
                    // Default behavior: Ignore all content until the title ender.  Assume most terminals don't know how to do this.
                    if (t == (char)UnicodeCommand.TITLEEND)
                    {
                        outputExpected = ExpectNextChar.NORMAL;
                    }
                    break;

                default:
                    switch (t)
                    {
                    case (char)UnicodeCommand.RESIZESCREEN:
                        outputExpected = ExpectNextChar.RESIZEWIDTH;
                        break;

                    case (char)UnicodeCommand.TITLEBEGIN:
                        outputExpected = ExpectNextChar.INTITLE;
                        break;

                    case (char)UnicodeCommand.STARTNEXTLINE:
                        sb.Append("\r\n");
                        break;

                    case (char)UnicodeCommand.LINEFEEDKEEPCOL:
                        sb.Append("\n");
                        break;

                    case (char)UnicodeCommand.GOTOLEFTEDGE:
                        sb.Append("\r");
                        break;

                    default:
                        sb.Append(t);         // default passhtrough
                        break;
                    }
                    break;
                }
            }

            // By this point, any UnicodeCommand chars still left must be un-mapped by any of the mappers:
            if (!AllowNativeUnicodeCommands)
            {
                StripUnicodeCommands(sb);
            }

            return(sb.ToString().ToCharArray());
        }
Example #4
0
        /// <summary>
        /// Respond to one single input character in Unicode, using the pretend
        /// virtual Unicode terminal keycodes described in the UnicodeCommand enum.
        /// To keep things simple, all key input is coerced into single Unicode chars
        /// even if the actual keypress takes multiple characters to express in its
        /// native form (i.e. ESC [ A means left-arrow on a VT100 terminal.  If
        /// a telnet is talking via VT100 codes, that ESC [ A will get converted into
        /// a single UnicdeCommand.LEFTCURSORONE character before being sent here.)
        /// <br/>
        /// This method is public because it is also how other mods should send input
        /// to the terminal if they want some other source to send simulated keystrokes.
        /// </summary>
        /// <param name="ch">The character, which might be a UnicodeCommand char</param>
        /// <param name="whichTelnet">If this came from a telnet session, which one did it come from?
        /// Set to null in order to say it wasn't from a telnet but was from the interactive GUI</param>
        /// <param name="doQueuing">true if the keypress should get queued if we're not ready for it
        /// right now.  If false, then the keypress will be ignored if we're not ready for it.</param>
        public void ProcessOneInputChar(char ch, TelnetSingletonServer whichTelnet, bool doQueuing = true)
        {
            // Weird exceptions for multi-char data combos that would have been begun on previous calls to this method:
            switch (inputExpected)
            {
                case ExpectNextChar.RESIZEWIDTH:
                    pendingWidth = ch;
                    inputExpected = ExpectNextChar.RESIZEHEIGHT;
                    return;
                case ExpectNextChar.RESIZEHEIGHT:
                    int height = ch;
                    shared.Screen.SetSize(height, pendingWidth);
                    inputExpected = ExpectNextChar.NORMAL;
                    return;
                default:
                    break;
            }

            // Printable ASCII section of Unicode - the common vanilla situation
            // (Idea: Since this is all Unicode anyway, should we allow a wider range to
            // include multi-language accent characters and so on?  Answer: to do so we'd
            // first need to expand the font pictures in the font image file, so it's a
            // bigger task than it may first seem.)
            if (0x0020 <= ch && ch <= 0x007f)
            {
                 Type(ch, doQueuing);
            }
            else
            {
                switch(ch)
                {
                    // A few conversions from UnicodeCommand into those parts of ASCII that it
                    // maps directly into nicely, otherwise just pass it through to SpecialKey():

                    case (char)UnicodeCommand.DELETELEFT:
                    case (char)8:
                        Type((char)8, doQueuing);
                        break;
                    case (char)UnicodeCommand.STARTNEXTLINE:
                    case '\r':
                        Type('\r', doQueuing);
                        break;
                    case '\t':
                        Type('\t', doQueuing);
                        break;
                    case (char)UnicodeCommand.RESIZESCREEN:
                        inputExpected = ExpectNextChar.RESIZEWIDTH;
                        break; // next expected char is the width.

                    // Finish session:  If GUI, then close window.  If Telnet, then detatch from the session:

                    case (char)0x0004/*control-D*/: // How users of unix shells are used to doing this.
                    case (char)0x0018/*control-X*/: // How kOS did it in the past in the GUI window.
                        if (shared.Interpreter.IsAtStartOfCommand())
                        {
                            if (whichTelnet == null)
                                Close();
                            else
                                whichTelnet.DisconnectFromProcessor();
                        }
                        break;

                    // User asking for redraw (Unity already requires that we continually redraw the GUI Terminal, so this is only meaningful for telnet):

                    case (char)UnicodeCommand.REQUESTREPAINT:
                        if (whichTelnet != null)
                        {
                            ResizeAndRepaintTelnet(whichTelnet, shared.Screen.ColumnCount, shared.Screen.RowCount, true);
                        }
                        break;

                    // Typical case is to just let SpecialKey do the work:

                    default:
                        SpecialKey(ch, doQueuing);
                        break;
                }
            }

            // else ignore it - unimplemented char.
        }
Example #5
0
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) on output to what the terminal
        /// wants to see.
        /// Subclasses of this should perform their own manipulations, then fall-through
        /// to this base class implementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public override char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                case ExpectNextChar.TELEPORTCURSORCOL:
                    pendingCol     = t;
                    outputExpected = ExpectNextChar.TELEPORTCURSORROW;
                    break;

                case ExpectNextChar.TELEPORTCURSORROW:
                    int row = t;
                    // VT100 counts rows and cols starting at 1, not 0, thus the +1's below:
                    sb.AppendFormat("{0}{1};{2}H", csi, (row + 1), (pendingCol + 1));
                    outputExpected = ExpectNextChar.NORMAL;
                    break;

                default:
                    switch (t)
                    {
                    case (char)UnicodeCommand.TELEPORTCURSOR:
                        outputExpected = ExpectNextChar.TELEPORTCURSORCOL;
                        break;

                    case (char)UnicodeCommand.CLEARSCREEN:
                        sb.AppendFormat("{0}2J{0}H", csi);
                        break;

                    case (char)UnicodeCommand.SCROLLSCREENUPONE:
                        sb.AppendFormat("{0}S", csi);
                        break;

                    case (char)UnicodeCommand.SCROLLSCREENDOWNONE:
                        sb.AppendFormat("{0}T", csi);
                        break;

                    case (char)UnicodeCommand.HOMECURSOR:
                        sb.AppendFormat("{0}H", csi);
                        break;

                    case (char)UnicodeCommand.UPCURSORONE:
                        sb.AppendFormat("{0}A", csi);
                        break;

                    case (char)UnicodeCommand.DOWNCURSORONE:
                        sb.AppendFormat("{0}B", csi);
                        break;

                    case (char)UnicodeCommand.RIGHTCURSORONE:
                        sb.AppendFormat("{0}C", csi);
                        break;

                    case (char)UnicodeCommand.LEFTCURSORONE:
                        sb.AppendFormat("{0}D", csi);
                        break;

                    case (char)UnicodeCommand.DELETELEFT:
                        sb.AppendFormat("{0}K", csi);
                        break;

                    case (char)UnicodeCommand.DELETERIGHT:
                        sb.AppendFormat("{0}1K", csi);
                        break;

                    case (char)UnicodeCommand.BEEP:
                        sb.Append(BELL_CHAR);
                        break;

                    case (char)UnicodeCommand.REVERSESCREENMODE:
                        sb.AppendFormat("{0}?5h", csi);
                        break;

                    case (char)UnicodeCommand.NORMALSCREENMODE:
                        sb.AppendFormat("{0}?5l", csi);
                        break;

                    case (char)UnicodeCommand.VISUALBEEPMODE:
                        // sadly, have to consume and ignore - no vt100 code for this, so it's not supported.
                        break;

                    case (char)UnicodeCommand.AUDIOBEEPMODE:
                        // sadly, have to consume and ignore - no vt100 code for this. so it's not supported.
                        break;

                    default:
                        sb.Append(t);         // default passhtrough
                        break;
                    }
                    break;
                }
            }
            return(base.OutputConvert(sb.ToString()));
        }
Example #6
0
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) on output to what the terminal
        /// wants to see.
        /// Subclasses of this should perform their own manipulations, then fall-through
        /// to this base class implementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public override char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                    case ExpectNextChar.TELEPORTCURSORCOL:
                        pendingCol = t;
                        outputExpected = ExpectNextChar.TELEPORTCURSORROW;
                        break;

                    case ExpectNextChar.TELEPORTCURSORROW:
                        int row = t;
                        // VT100 counts rows and cols starting at 1, not 0, thus the +1's below:
                        sb.AppendFormat("{0}{1};{2}H", csi, (row + 1), (pendingCol + 1));
                        outputExpected = ExpectNextChar.NORMAL;
                        break;

                    default:
                        switch (t)
                        {
                            case (char)UnicodeCommand.TELEPORTCURSOR:
                                outputExpected = ExpectNextChar.TELEPORTCURSORCOL;
                                break;

                            case (char)UnicodeCommand.CLEARSCREEN:
                                sb.AppendFormat("{0}2J{0}H", csi);
                                break;

                            case (char)UnicodeCommand.SCROLLSCREENUPONE:
                                sb.AppendFormat("{0}S", csi);
                                break;

                            case (char)UnicodeCommand.SCROLLSCREENDOWNONE:
                                sb.AppendFormat("{0}T", csi);
                                break;

                            case (char)UnicodeCommand.HOMECURSOR:
                                sb.AppendFormat("{0}H", csi);
                                break;

                            case (char)UnicodeCommand.UPCURSORONE:
                                sb.AppendFormat("{0}A", csi);
                                break;

                            case (char)UnicodeCommand.DOWNCURSORONE:
                                sb.AppendFormat("{0}B", csi);
                                break;

                            case (char)UnicodeCommand.RIGHTCURSORONE:
                                sb.AppendFormat("{0}C", csi);
                                break;

                            case (char)UnicodeCommand.LEFTCURSORONE:
                                sb.AppendFormat("{0}D", csi);
                                break;

                            case (char)UnicodeCommand.DELETELEFT:
                                sb.AppendFormat("{0}K", csi);
                                break;

                            case (char)UnicodeCommand.DELETERIGHT:
                                sb.AppendFormat("{0}1K", csi);
                                break;

                            case (char)UnicodeCommand.BEEP:
                                sb.Append(BELL_CHAR);
                                break;
                                
                            case (char)UnicodeCommand.REVERSESCREENMODE:
                                sb.AppendFormat("{0}?5h", csi);
                                break;
                                
                            case (char)UnicodeCommand.NORMALSCREENMODE:
                                sb.AppendFormat("{0}?5l", csi);
                                break;
                                
                            case (char)UnicodeCommand.VISUALBEEPMODE:
                                // sadly, have to consume and ignore - no vt100 code for this, so it's not supported.
                                break;
                                
                            case (char)UnicodeCommand.AUDIOBEEPMODE:
                                // sadly, have to consume and ignore - no vt100 code for this. so it's not supported.
                                break;
                                
                            default:
                                sb.Append(t); // default passhtrough
                                break;
                        }
                        break;
                }
            }
            return base.OutputConvert(sb.ToString());
        }
Example #7
0
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) on output to what the terminal
        /// wants to see.
        /// Subclasses of this should perform their own manipulations, then fall-through
        /// to this base class implementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public override char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                case ExpectNextChar.TELEPORTCURSORCOL:
                    pendingCol     = t;
                    outputExpected = ExpectNextChar.TELEPORTCURSORROW;
                    break;

                case ExpectNextChar.TELEPORTCURSORROW:
                    int row = t;
                    // VT100 counts rows and cols starting at 1, not 0, thus the +1's below:
                    sb.AppendFormat("{0}{1};{2}H", csi, (row + 1), (pendingCol + 1));
                    outputExpected = ExpectNextChar.NORMAL;
                    break;

                default:
                    switch (t)
                    {
                    case (char)UnicodeCommand.TELEPORTCURSOR:
                        outputExpected = ExpectNextChar.TELEPORTCURSORCOL;
                        break;

                    case (char)UnicodeCommand.CLEARSCREEN:
                        sb.AppendFormat("{0}2J{0}H", csi);
                        break;

                    case (char)UnicodeCommand.SCROLLSCREENUPONE:
                        sb.AppendFormat("{0}S", csi);
                        break;

                    case (char)UnicodeCommand.SCROLLSCREENDOWNONE:
                        sb.AppendFormat("{0}T", csi);
                        break;

                    case (char)UnicodeCommand.HOMECURSOR:
                        sb.AppendFormat("{0}H", csi);
                        break;

                    case (char)UnicodeCommand.UPCURSORONE:
                        sb.AppendFormat("{0}A", csi);
                        break;

                    case (char)UnicodeCommand.DOWNCURSORONE:
                        sb.AppendFormat("{0}B", csi);
                        break;

                    case (char)UnicodeCommand.RIGHTCURSORONE:
                        sb.AppendFormat("{0}C", csi);
                        break;

                    case (char)UnicodeCommand.LEFTCURSORONE:
                        sb.AppendFormat("{0}D", csi);
                        break;

                    case (char)UnicodeCommand.DELETELEFT:
                        sb.AppendFormat("{0}K", csi);
                        break;

                    case (char)UnicodeCommand.DELETERIGHT:
                        sb.AppendFormat("{0}1K", csi);
                        break;

                    default:
                        sb.Append(t);         // default passhtrough
                        break;
                    }
                    break;
                }
            }
            return(base.OutputConvert(sb.ToString()));
        }
Example #8
0
        /// <summary>
        /// Respond to one single input character in Unicode, using the pretend
        /// virtual Unicode terminal keycodes described in the UnicodeCommand enum.
        /// To keep things simple, all key input is coerced into single Unicode chars
        /// even if the actual keypress takes multiple characters to express in its
        /// native form (i.e. ESC [ A means left-arrow on a VT100 terminal.  If
        /// a telnet is talking via VT100 codes, that ESC [ A will get converted into
        /// a single UnicdeCommand.LEFTCURSORONE character before being sent here.)
        /// <br/>
        /// This method is public because it is also how other mods should send input
        /// to the terminal if they want some other source to send simulated keystrokes.
        /// </summary>
        /// <param name="ch">The character, which might be a UnicodeCommand char</param>
        /// <param name="whichTelnet">If this came from a telnet session, which one did it come from?
        /// Set to null in order to say it wasn't from a telnet but was from the interactive GUI</param>
        public void ProcessOneInputChar(char ch, TelnetSingletonServer whichTelnet)
        {
            // Weird exceptions for multi-char data combos that would have been begun on previous calls to this method:
            switch (inputExpected)
            {
            case ExpectNextChar.RESIZEWIDTH:
                pendingWidth  = ch;
                inputExpected = ExpectNextChar.RESIZEHEIGHT;
                return;

            case ExpectNextChar.RESIZEHEIGHT:
                int height = ch;
                shared.Screen.SetSize(height, pendingWidth);
                inputExpected = ExpectNextChar.NORMAL;
                return;

            default:
                break;
            }

            // Printable ASCII section of Unicode - the common vanilla situation
            // (Idea: Since this is all Unicode anyway, should we allow a wider range to
            // include multi-language accent characters and so on?  Answer: to do so we'd
            // first need to expand the font pictures in the font image file, so it's a
            // bigger task than it may first seem.)
            if (0x0020 <= ch && ch <= 0x007f)
            {
                Type(ch);
            }
            else
            {
                switch (ch)
                {
                // A few conversions from UnicodeCommand into those parts of ASCII that it
                // maps directly into nicely, otherwise just pass it through to SpecialKey():

                case (char)UnicodeCommand.DELETELEFT:
                    Type((char)8);
                    break;

                case (char)UnicodeCommand.STARTNEXTLINE:
                    Type('\r');
                    break;

                case '\t':
                    Type('\t');
                    break;

                case (char)UnicodeCommand.RESIZESCREEN:
                    inputExpected = ExpectNextChar.RESIZEWIDTH;
                    break;     // next expected char is the width.

                // Finish session:  If GUI, then close window.  If Telnet, then detatch from the session:

                case (char)0x0004 /*control-D*/:    // How users of unix shells are used to doing this.
                case (char)0x0018 /*control-X*/:    // How kOS did it in the past in the GUI window.
                    if (shared.Interpreter.IsAtStartOfCommand())
                    {
                        if (whichTelnet == null)
                        {
                            Close();
                        }
                        else
                        {
                            whichTelnet.DisconnectFromProcessor();
                        }
                    }
                    break;

                // User asking for redraw (Unity already requires that we continually redraw the GUI Terminal, so this is only meaningful for telnet):

                case (char)UnicodeCommand.REQUESTREPAINT:
                    if (whichTelnet != null)
                    {
                        ResizeAndRepaintTelnet(whichTelnet, shared.Screen.ColumnCount, shared.Screen.RowCount, true);
                    }
                    break;

                // Typical case is to just let SpecialKey do the work:

                default:
                    SpecialKey(ch);
                    break;
                }
            }

            // else ignore it - unimplemented char.
        }
        /// <summary>
        /// Map the Unicode chars (and the fake control codes we made) into what the terminal
        /// wants to see.
        /// In this base class, all it does is just mostly passthru things as-is with no
        /// conversions.
        /// Subclasses of this should perform their own manipulations, then fallthrough
        /// to this base class inmplementation at the bottom, to allow chains of
        /// subclasses to all operate on the data.
        /// </summary>
        /// <param name="str">Unicode char</param>
        /// <returns>raw byte stream to send to the terminal</returns>
        public virtual char[] OutputConvert(string str)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char t in str)
            {
                switch (outputExpected)
                {
                    case ExpectNextChar.RESIZEWIDTH:
                        pendingWidth = t;
                        outputExpected = ExpectNextChar.RESIZEHEIGHT;
                        break;
                    case ExpectNextChar.RESIZEHEIGHT:
                        int height = t;
                        sb.Append("{Please resize to " + pendingWidth + "x" + height + "}"); // By default, assume the terminal has no such control code, but this can be overridden.
                        outputExpected = ExpectNextChar.NORMAL;
                        break;
                    case ExpectNextChar.INTITLE:
                        // Default behavior: Ignore all content until the title ender.  Assume most terminals don't know how to do this.
                        if (t == (char)UnicodeCommand.TITLEEND)
                            outputExpected = ExpectNextChar.NORMAL;
                        break;
                    default:
                        switch (t)
                        {
                            case (char)UnicodeCommand.RESIZESCREEN:
                                outputExpected = ExpectNextChar.RESIZEWIDTH;
                                break;
                            case (char)UnicodeCommand.TITLEBEGIN:
                                outputExpected = ExpectNextChar.INTITLE;
                                break;
                            case (char)UnicodeCommand.STARTNEXTLINE:
                                sb.Append("\r\n");
                                break;
                            case (char)UnicodeCommand.LINEFEEDKEEPCOL:
                                sb.Append("\n");
                                break;
                            case (char)UnicodeCommand.GOTOLEFTEDGE:
                                sb.Append("\r");
                                break;
                            default: 
                                sb.Append(t); // default passhtrough
                                break;
                        }
                        break;
                }
            }

            // By this point, any UnicodeCommand chars still left must be un-mapped by any of the mappers:
            if (!AllowNativeUnicodeCommands)
                StripUnicodeCommands(sb);

            return sb.ToString().ToCharArray();
        }