protected override void OnBeforeCommand(BeforeCommandEventArgs e)
 {
   if (e.Command.StartsWith("title", System.StringComparison.OrdinalIgnoreCase))
   {
     OutputTextBox Output = (OutputTextBox)OutputBox;
     Output.PermanentCaption = null;
     if ((e.Command.Length > 5) && (e.Command[5] == ' '))
       Output.PermanentCaption = e.Command.Substring(6).Trim();
     Output.UpdateTabCaption();
   }
   base.OnBeforeCommand(e);
 }
    private void OutputBox_KeyDown(object sender, KeyEventArgs e)
    {
      if (!Running)
      {
        Dispose();
        return;
      }

      // When CMD is not idling we will skip input buffer processing
      if (!Idling)
        return;

      switch (e.KeyData)
      {
        case Keys.Back:
          if (_InputIndex > 0)
          {
            ReplaceOutputText(_OutputBox.TextLength - _InputBuilder.Length + _InputIndex - 1, 1, string.Empty);

            if (_InputIndex < _InputBuilder.Length)
              _InputBuilder.Remove(_InputIndex - 1, 1);
            else
              _InputBuilder.Length--;
            _InputIndex--;

            UpdateCaretPosition();
          }
          e.SuppressKeyPress = true;
          break;
        case Keys.Return:
          ReplaceOutputText(_OutputBox.TextLength - _InputBuilder.Length, _InputBuilder.Length, string.Empty);

          BeforeCommandEventArgs BeforeCommandArgs = new BeforeCommandEventArgs(_InputBuilder.ToString());
          _InputBuilder.Length = 0;
          _InputIndex = 0;

          OnBeforeCommand(BeforeCommandArgs);
          if (!BeforeCommandArgs.Cancel)
          {
            if (EchoOff)
              _OutputBox.AppendText(BeforeCommandArgs.Command + "\r\n");
            WriteLineToStandardInput(BeforeCommandArgs.Command);
          }

          _OutputBox.Select(int.MaxValue, 0);
          _OutputBox.ScrollToCaret();
          e.SuppressKeyPress = true;
          break;
        case Keys.Escape:
          if (_InputBuilder.Length > 0)
          {
            ReplaceOutputText(_OutputBox.TextLength - _InputBuilder.Length, _InputBuilder.Length, string.Empty);

            _InputBuilder.Length = 0;
            _InputIndex = 0;

            UpdateCaretPosition();
          }
          e.SuppressKeyPress = true;
          break;
        case Keys.End:
          if (_InputIndex < _InputBuilder.Length)
          {
            _InputIndex = _InputBuilder.Length;
            UpdateCaretPosition();
          }
          break;
        case Keys.Home:
          if (_InputIndex > 0)
          {
            _InputIndex = 0;
            UpdateCaretPosition();
          }
          break;
        case Keys.Left:
          if (_InputIndex > 0)
          {
            _InputIndex--;
            UpdateCaretPosition();
          }
          break;
        case Keys.Right:
          if (_InputIndex < _InputBuilder.Length)
          {
            _InputIndex++;
            UpdateCaretPosition();
          }
          break;
        case Keys.Delete:
          if (_InputIndex < _InputBuilder.Length)
          {
            ReplaceOutputText(_OutputBox.TextLength - _InputBuilder.Length + _InputIndex, 1, string.Empty);

            if (_InputIndex < _InputBuilder.Length)
              _InputBuilder.Remove(_InputIndex, 1);
            else
              _InputBuilder.Length--;

            UpdateCaretPosition();
          }
          break;
        case Keys.Tab:
          e.SuppressKeyPress = true;
          int StartIndex = -1;
          int QuoteIndex = -1;
          int QuoteCount = 0;

          for (int I = _InputIndex - 1; I >= 0; I--)
          {
            if ((_InputBuilder[I] == ' ') && (StartIndex < 0))
              StartIndex = I;
            else
              if (_InputBuilder[I] == '"')
              {
                if (QuoteIndex < 0)
                  QuoteIndex = I;
                QuoteCount++;
              }
          }

          if (QuoteCount % 2 == 0)
          {
            QuoteIndex = -1;
            StartIndex++;
          }
          else
            StartIndex = QuoteIndex + 1;

          int EndIndex = _InputIndex;
          while ((EndIndex < _InputBuilder.Length) &&
            ((QuoteIndex < 0) || (_InputBuilder[EndIndex] != '"')) && ((QuoteIndex >= 0) || (_InputBuilder[EndIndex] != ' ')))
            EndIndex++;

          if (StartIndex < _InputIndex)
          {
            string OriginalString = _InputBuilder.ToString(StartIndex, _InputIndex - StartIndex);
            SubstituteEventArgs SubstituteArgs = new SubstituteEventArgs(OriginalString);
            OnSubstitute(SubstituteArgs);

            string ReplaceString = SubstituteArgs.SubstituteString;
            if (!string.Equals(OriginalString, ReplaceString))
            {
              if (QuoteIndex >= 0)
              {
                if (EndIndex >= _InputBuilder.Length)
                  ReplaceString += '"';
              }
              else
              {
                if (ReplaceString.IndexOf(' ') >= 0)
                  ReplaceString = '"' + ReplaceString + '"';
              }

              int ReplaceLength = EndIndex - StartIndex;
              ReplaceOutputText(_OutputBox.TextLength - _InputBuilder.Length + StartIndex, ReplaceLength, ReplaceString);
              _InputBuilder.Remove(StartIndex, ReplaceLength);
              _InputBuilder.Insert(StartIndex, ReplaceString);
              _InputIndex = StartIndex + ReplaceString.Length;
              UpdateCaretPosition();
            }
          }
          break;
        case Keys.V | Keys.Control:
        case Keys.Insert | Keys.Control:
          e.SuppressKeyPress = true;
          PasteFromClipboard();
          break;
        default:
          e.Handled = true;
          break;
      }
    }
    public void SendCommand(string command, bool echo)
    {
      if (command == null)
        throw new ArgumentNullException();
      if (_OutputBox == null)
        throw new InvalidOperationException();

      if (_CmdProcess == null)
        throw new ObjectDisposedException("CommandProcessorController");
      else
        if (_CmdProcess.HasExited)
        {
          Dispose();
          throw new ObjectDisposedException("CommandProcessorController");
        }

      if (!_IdleEvent.WaitOne(0, false))
        throw new InvalidOperationException();

      BeforeCommandEventArgs Args = new BeforeCommandEventArgs(command);
      OnBeforeCommand(Args);
      if (Args.Cancel)
        return;

      // Clear input buffer if any, because its content can mess with command output
      if (_InputBuilder.Length > 0)
      {
        ReplaceOutputText(_OutputBox.TextLength - _InputBuilder.Length, _InputBuilder.Length, string.Empty);
        _InputBuilder.Length = 0;
        _InputIndex = 0;
      }

      if (echo && EchoOff)
        _OutputBox.AppendText(Args.Command + "\r\n");

      _SkipOutput = !echo;
      try
      {
        _IdleEvent.Reset();
        WriteLineToStandardInput(Args.Command);
        _IdleEvent.WaitOne();
      }
      finally
      {
        _SkipOutput = false;
      }
    }
 protected virtual void OnBeforeCommand(BeforeCommandEventArgs e)
 {
   var BeforeCommand = Events[EventBeforeCommand] as EventHandler<BeforeCommandEventArgs>;
   if (BeforeCommand != null)
     BeforeCommand(this, e);
 }