/*******************************************************************************
 * Copyright (c) 2003, 2011 Wind River Systems, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package com.google.eclipse.elt.emulator.core;

import static org.eclipse.core.runtime.Status.OK_STATUS;
import static org.eclipse.jface.bindings.keys.SWTKeySupport.convertEventToUnmodifiedAccelerator;

import static com.google.eclipse.elt.emulator.impl.TerminalPlugin.isOptionEnabled;

import java.io.*;
import java.net.SocketException;
import java.util.List;

import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.*;
import org.eclipse.ui.keys.IBindingService;

import com.google.eclipse.elt.emulator.control.*;
import com.google.eclipse.elt.emulator.impl.*;
import com.google.eclipse.elt.emulator.model.*;
import com.google.eclipse.elt.emulator.provisional.api.*;
import com.google.eclipse.elt.emulator.textcanvas.*;
import com.google.eclipse.elt.emulator.textcanvas.PipedInputStream;

public class VT100TerminalControl implements ITerminalControlForText, ITerminalControl, ITerminalViewControl {
  protected static final String[] LINE_DELIMITERS = { "\n" };

  private static final String DEFAULT_ENCODING =
      new InputStreamReader(new ByteArrayInputStream(new byte[0])).getEncoding();

  // This field holds a reference to a TerminalText object that performs all ANSI text processing on data received from
  // the remote host and controls how text is displayed using the view's StyledText widget.
  private final VT100Emulator terminalText;

  private Display display;
  private TextCanvas textControl;
  private Composite rootControl;
  private Clipboard clipboard;
  private KeyListener keyHandler;
  private final ITerminalListener terminalListener;
  private String message = "";
  private FocusListener fFocusListener;
  private ITerminalConnector connector;
  private final ITerminalConnector[] connectors;
  private final PipedInputStream inputStream;
  private String encoding = DEFAULT_ENCODING;
  private InputStreamReader inputStreamReader;
  private ICommandInputField commandInputField;
  private volatile TerminalState state;
  private final ITerminalTextData terminalModel;

  volatile private Job job;

  private final EditActionAccelerators editActionAccelerators = new EditActionAccelerators();

  public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
    this.connectors = connectors;
    terminalListener = target;
    terminalModel = TerminalTextDataFactory.makeTerminalTextData();
    terminalModel.setMaxHeight(1000);
    inputStream = new PipedInputStream(8 * 1024);
    terminalText = new VT100Emulator(terminalModel, this, null);
    try {
      // Use default Encoding as start, until setEncoding() is called.
      setEncoding(null);
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      // Fall back to local platform default encoding
      encoding = DEFAULT_ENCODING;
      inputStreamReader = new InputStreamReader(inputStream);
      terminalText.setInputStreamReader(inputStreamReader);
    }
    setUpTerminal(wndParent);
  }

  @Override public void setEncoding(String encoding) throws UnsupportedEncodingException {
    if (encoding == null) {
      encoding = "ISO-8859-1";
    }
    inputStreamReader = new InputStreamReader(inputStream, encoding);
    // remember encoding if above didn't throw an exception
    this.encoding = encoding;
    terminalText.setInputStreamReader(inputStreamReader);
  }

  @Override public String getEncoding() {
    return encoding;
  }

  @Override public ITerminalConnector[] getConnectors() {
    return connectors;
  }

  @Override public void copy() {
    copy(DND.CLIPBOARD);
  }

  private void copy(int clipboardType) {
    String selection = getSelection();
    if (selection == null || selection.isEmpty()) {
      return;
    }
    Object[] data = new Object[] { selection };
    Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
    clipboard.setContents(data, types, clipboardType);
  }

  @Override public void paste() {
    paste(DND.CLIPBOARD);
  }

  private void paste(int clipboardType) {
    TextTransfer textTransfer = TextTransfer.getInstance();
    String strText = (String) clipboard.getContents(textTransfer, clipboardType);
    pasteString(strText);
  }

  @Override public boolean pasteString(String text) {
    if (!isConnected()) {
      return false;
    }
    if (text == null) {
      return false;
    }
    if (!encoding.equals(DEFAULT_ENCODING)) {
      sendString(text);
    } else {
      // TODO I do not understand why pasteString would do this here...
      for (int i = 0; i < text.length(); i++) {
        sendChar(text.charAt(i), false);
      }
    }
    return true;
  }

  @Override public void selectAll() {
    getTextControl().selectAll();
  }

  @Override public void sendKey(char character) {
    Event event;
    KeyEvent keyEvent;
    event = new Event();
    event.widget = getTextControl();
    event.character = character;
    event.keyCode = 0;
    event.stateMask = 0;
    event.doit = true;
    keyEvent = new KeyEvent(event);
    keyHandler.keyPressed(keyEvent);
  }

  @Override public void clearTerminal() {
    getTerminalText().clearTerminal();
  }

  @Override public Clipboard getClipboard() {
    return clipboard;
  }

  @Override public String getSelection() {
    String text = textControl.getSelectionText();
    return text == null ? "" : text;
  }

  @Override public boolean setFocus() {
    return getTextControl().setFocus();
  }

  @Override public boolean isEmpty() {
    return getTextControl().isEmpty();
  }

  @Override public boolean isDisposed() {
    return getTextControl().isDisposed();
  }

  @Override public boolean isConnected() {
    return state == TerminalState.CONNECTED;
  }

  @Override public void disposeTerminal() {
    disconnectTerminal();
    clipboard.dispose();
    getTerminalText().dispose();
  }

  @Override public void connectTerminal() {
    if (getTerminalConnector() == null) {
      return;
    }
    terminalText.resetState();
    if (connector.getInitializationErrorMessage() != null) {
      showErrorMessage(NLS.bind(TerminalMessages.cannotConnectTo, connector.getName(),
          connector.getInitializationErrorMessage()));
      return;
    }
    getTerminalConnector().connect(this);
    // clean the error message
    setErrorMessage("");
    waitForConnect();
  }

  @Override public ITerminalConnector getTerminalConnector() {
    return connector;
  }

  @Override public void disconnectTerminal() {
    Logger.log("entered.");
    // Disconnect the remote side first.
    if (getState() != TerminalState.CLOSED && getTerminalConnector() != null) {
      getTerminalConnector().disconnect();
    }
    // Ensure that a new Job can be started; then clean up old Job.
    Job newJob;
    synchronized (this) {
      newJob = job;
      job = null;
    }
    if (newJob != null) {
      newJob.cancel();
      // Join job to avoid leaving job running after workbench shutdown (333613).
      // Interrupt to be fast enough; cannot close fInputStream since it is re-used (bug 348700).
      Thread t = newJob.getThread();
      if (t != null) {
        t.interrupt();
      }
      try {
        newJob.join();
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      }
    }
  }

  private void waitForConnect() {
    // TODO
    // Eliminate this code
    while (getState() == TerminalState.CONNECTING) {
      if (display.readAndDispatch()) {
        continue;
      }
      display.sleep();
    }
    if (getTextControl().isDisposed()) {
      disconnectTerminal();
      return;
    }
    if (!getMsg().isEmpty()) {
      showErrorMessage(getMsg());
      disconnectTerminal();
      return;
    }
    getTextControl().setFocus();
    startReaderJob();
  }

  private synchronized void startReaderJob() {
    if (job == null) {
      initializeJob();
      job.setSystem(true);
      job.schedule();
    }
  }

  private void initializeJob() {
    job = new Job("Terminal data reader") {
      @Override protected IStatus run(IProgressMonitor monitor) {
        IStatus status = OK_STATUS;
        try {
          while (true) {
            while (inputStream.available() == 0 && !monitor.isCanceled()) {
              try {
                inputStream.waitForAvailable(500);
              } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
              }
            }
            if (monitor.isCanceled()) {
              // Do not disconnect terminal here because another reader job may already be running.
              status = Status.CANCEL_STATUS;
              break;
            }
            try {
              // TODO: should block when no text is available!
              terminalText.processText();
            } catch (Exception e) {
              disconnectTerminal();
              status = new Status(IStatus.ERROR, TerminalPlugin.PLUGIN_ID, e.getLocalizedMessage(), e);
              break;
            }
          }
        } finally {
          // Clean the job: start a new one when the connection gets restarted.
          // Bug 208145: make sure we do not clean an other job that's already started (since it would become a zombie)
          synchronized (VT100TerminalControl.this) {
            if (job == this) {
              job = null;
            }
          }
        }
        return status;
      }
    };
  }

  private void showErrorMessage(String message) {
    String title = TerminalMessages.terminalError;
    MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
    mb.setText(title);
    mb.setMessage(message);
    mb.open();
  }

  protected void sendString(String string) {
    try {
      // Send the string after converting it to an array of bytes using the platform's default character encoding.
      //
      // TODO: Find a way to force this to use the ISO Latin-1 encoding.
      // TODO: handle Encoding Errors in a better way
      getOutputStream().write(string.getBytes(encoding));
      getOutputStream().flush();
    } catch (SocketException socketException) {
      displayTextInTerminal(socketException.getMessage());
      String strMsg = TerminalMessages.socketError + "!\n" + socketException.getMessage();
      showErrorMessage(strMsg);
      Logger.logException(socketException);
      disconnectTerminal();
    } catch (IOException ioException) {
      showErrorMessage(TerminalMessages.ioError + "!\n" + ioException.getMessage());
      Logger.logException(ioException);
      disconnectTerminal();
    }
  }

  @Override public Shell getShell() {
    return getTextControl().getShell();
  }

  protected void sendChar(char chKey, boolean altKeyPressed) {
    try {
      String text = Character.toString(chKey);
      byte[] bytes = text.getBytes(getEncoding());
      OutputStream os = getOutputStream();
      if (os == null) {
        // Bug 207785: NPE when trying to send char while no longer connected
        Logger.log("NOT sending '" + text + "' because no longer connected");
      } else {
        if (altKeyPressed) {
          // When the ALT key is pressed at the same time that a character is typed, translate it into an ESCAPE
          // followed by the character. The alternative in this case is to set the high bit of the character being
          // transmitted, but that will cause input such as ALT-f to be seen as the ISO Latin-1 character '�', which
          // can be confusing to European users running Emacs, for whom Alt-f should move forward a word instead of
          // inserting the '�' character.
          //
          // TODO: Make the ESCAPE-vs-highbit behavior user configurable.
          Logger.log("sending ESC + '" + text + "'");
          getOutputStream().write('\u001b');
          getOutputStream().write(bytes);
        } else {
          Logger.log("sending '" + text + "'");
          getOutputStream().write(bytes);
        }
        getOutputStream().flush();
      }
    } catch (SocketException socketException) {
      Logger.logException(socketException);
      displayTextInTerminal(socketException.getMessage());
      String message = TerminalMessages.socketError + "!\n" + socketException.getMessage();
      showErrorMessage(message);
      Logger.logException(socketException);
      disconnectTerminal();
    } catch (IOException ioException) {
      Logger.logException(ioException);
      displayTextInTerminal(ioException.getMessage());
      String message = TerminalMessages.ioError + "!\n" + ioException.getMessage();
      showErrorMessage(message);
      Logger.logException(ioException);
      disconnectTerminal();
    }
  }

  @Override public void setUpTerminal(Composite parent) {
    Assert.isNotNull(parent);
    state = TerminalState.CLOSED;
    setUpControls(parent);
    setupListeners();
  }

  @Override public void setFont(Font font) {
    getTextControl().setFont(font);
    if (commandInputField != null) {
      commandInputField.setFont(font);
    }
    // Tell the TerminalControl singleton that the font has changed.
    textControl.onFontChange();
    getTerminalText().fontChanged();
  }

  @Override public Font getFont() {
    return getTextControl().getFont();
  }

  @Override public Control getControl() {
    return textControl;
  }

  @Override public Control getRootControl() {
    return rootControl;
  }

  protected void setUpControls(Composite parent) {
    // The Terminal view now aims to be an ANSI-conforming terminal emulator, so it can't have a horizontal scroll bar
    // (but a vertical one is ok). Also, do _not_ make the TextViewer read-only, because that prevents it from seeing a
    // TAB character when the user presses TAB (instead, the TAB causes focus to switch to another Workbench control).
    // We prevent local keyboard input from modifying the text in method TerminalVerifyKeyListener.verifyKey().
    rootControl = new Composite(parent, SWT.NONE);
    GridLayout layout = new GridLayout();
    layout.marginWidth = 0;
    layout.marginHeight = 0;
    layout.verticalSpacing = 0;
    rootControl.setLayout(layout);
    ITerminalTextDataSnapshot snapshot = terminalModel.makeSnapshot();
    // TODO how to get the initial size correctly!
    snapshot.updateSnapshot(false);
    ITextCanvasModel canvasModel = new PollingTextCanvasModel(snapshot);
    textControl = new TextCanvas(rootControl, canvasModel, SWT.NONE, new TextLineRenderer(textControl, canvasModel));
    textControl.addMouseListener(new MouseAdapter() {
      @Override public void mouseUp(MouseEvent e) {
        IHyperlink hyperlink = hyperlinkAt(e);
        if (hyperlink != null) {
          hyperlink.open();
        }
      }
    });
    textControl.addMouseMoveListener(new MouseMoveListener() {
      @Override public void mouseMove(MouseEvent e) {
        IHyperlink hyperlink = hyperlinkAt(e);
        int cursorId = (hyperlink == null) ? SWT.CURSOR_IBEAM : SWT.CURSOR_HAND;
        Cursor newCursor = textControl.getDisplay().getSystemCursor(cursorId);
        if (!newCursor.equals(textControl.getCursor())) {
          textControl.setCursor(newCursor);
        }
      }
    });
    textControl.setLayoutData(new GridData(GridData.FILL_BOTH));
    textControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    textControl.addResizeHandler(new TextCanvas.ResizeListener() {
      @Override public void sizeChanged(int lines, int columns) {
        terminalText.setDimensions(lines, columns);
      }
    });
    textControl.addMouseListener(new MouseAdapter() {
      @Override public void mouseUp(MouseEvent e) {
        // update selection used by middle mouse button paste
        if (e.button == 1 && getSelection().length() > 0) {
          copy(DND.SELECTION_CLIPBOARD);
        }
      }
    });
    display = getTextControl().getDisplay();
    clipboard = new Clipboard(display);
    setFont(JFaceResources.getTextFont());
  }

  private IHyperlink hyperlinkAt(MouseEvent e) {
    Point p = textControl.screenPointToCell(e.x, e.y);
    if (p != null) {
      List<IHyperlink> hyperlinks = terminalText.hyperlinksAt(p.y);
      for (IHyperlink hyperlink : hyperlinks) {
        IRegion region = hyperlink.getHyperlinkRegion();
        int start = region.getOffset();
        int end = start + region.getLength() - 1;
        if (p.x >= start && p.x <= end) {
          return hyperlink;
        }
      }
    }
    return null;
  }

  protected void setupListeners() {
    keyHandler = new TerminalKeyHandler();
    fFocusListener = new TerminalFocusListener();
    getTextControl().addKeyListener(keyHandler);
    getTextControl().addFocusListener(fFocusListener);
  }

  @Override public void displayTextInTerminal(String text) {
    writeToTerminal("\r\n" + text + "\r\n");
  }

  private void writeToTerminal(String text) {
    try {
      getRemoteToTerminalOutputStream().write(text.getBytes(encoding));
    } catch (UnsupportedEncodingException e) {
      // should never happen!
      e.printStackTrace();
    } catch (IOException e) {
      // should never happen!
      e.printStackTrace();
    }
  }

  @Override public OutputStream getRemoteToTerminalOutputStream() {
    if (Logger.isLogEnabled()) {
      return new LoggingOutputStream(inputStream.getOutputStream());
    }
    return inputStream.getOutputStream();
  }

  protected boolean isLogCharEnabled() {
    return isOptionEnabled(Logger.TRACE_DEBUG_LOG_CHAR);
  }

  protected boolean isLogBufferSizeEnabled() {
    return isOptionEnabled(Logger.TRACE_DEBUG_LOG_BUFFER_SIZE);
  }

  @Override public OutputStream getOutputStream() {
    if (getTerminalConnector() != null) {
      return getTerminalConnector().getTerminalToRemoteStream();
    }
    return null;
  }

  @Override public void setErrorMessage(String message) {
    this.message = message;
  }

  public String getMsg() {
    return message;
  }

  protected TextCanvas getTextControl() {
    return textControl;
  }

  public VT100Emulator getTerminalText() {
    return terminalText;
  }

  protected class TerminalFocusListener implements FocusListener {
    private IContextActivation contextActivation = null;

    @Override public void focusGained(FocusEvent event) {
      // Disable all keyboard accelerators (e.g., Control-B) so the Terminal view can see every key stroke. Without
      // this, Emacs, vi, and Bash are unusable in the terminal view.
      IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
      bindingService.setKeyFilterEnabled(false);
      // The above code fails to cause Eclipse to disable menu-activation accelerators (e.g., Alt-F for the File menu),
      // so we set the command context to be the Terminal view's command context. This enables us to override
      // menu-activation accelerators with no-op commands in our plugin.xml file, which enables the terminal view to see
      // absolutly _all_ key-presses.
      IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
      contextActivation = contextService.activateContext("com.google.eclipse.elt.emulator.TerminalContext");
    }

    @Override public void focusLost(FocusEvent event) {
      // Enable all key bindings.
      IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
      bindingService.setKeyFilterEnabled(true);
      // Restore the command context to its previous value.
      IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
      contextService.deactivateContext(contextActivation);
    }
  }

  protected class TerminalKeyHandler extends KeyAdapter {
    @Override public void keyPressed(KeyEvent event) {
      if (getState() == TerminalState.CONNECTING) {
        return;
      }
      int accelerator = convertEventToUnmodifiedAccelerator(event);
      if (editActionAccelerators.isCopyAction(accelerator)) {
        copy();
        return;
      }
      if (editActionAccelerators.isPasteAction(accelerator)) {
        paste();
        return;
      }
      // We set the event.doit to false to prevent any further processing of this key event. The only reason this is
      // here is because I was seeing the F10 key both send an escape sequence (due to this method) and switch focus to
      // the Workbench File menu (forcing the user to click in the terminal view again to continue entering text). This
      // fixes that.
      event.doit = false;
      char character = event.character;
      if (state == TerminalState.CLOSED) {
        // Pressing ENTER while not connected causes us to connect.
        if (character == '\r') {
          connectTerminal();
          return;
        }
        // Ignore all other keyboard input when not connected.
        // Allow other key handlers (such as Ctrl+F1) do their work.
        event.doit = true;
        return;
      }
      // Manage the Del key
      if (event.keyCode == 0x000007f) {
        sendString("\u001b[3~");
        return;
      }
      // If the event character is NUL ('\u0000'), then a special key was pressed (e.g., PageUp, PageDown, an arrow key,
      // a function key, Shift, Alt, Control, etc.). The one exception is when the user presses Control-@, which sends a
      // NUL character, in which case we must send the NUL to the remote endpoint. This is necessary so that Emacs will
      // work correctly, because Control-@ (i.e., NUL) invokes Emacs' set-mark-command when Emacs is running on a
      // terminal. When the user presses Control-@, the keyCode is 50.
      if (character == '\u0000' && event.keyCode != 50) {
        // A special key was pressed. Figure out which one it was and send the appropriate ANSI escape sequence.
        //
        // IMPORTANT: Control will not enter this method for these special keys unless certain <keybinding> tags are
        // present in the plugin.xml file for the Terminal view. Do not delete those tags.
        switch (event.keyCode) {
        case 0x1000001: // Up arrow.
          sendString("\u001b[A");
          break;
        case 0x1000002: // Down arrow.
          sendString("\u001b[B");
          break;
        case 0x1000003: // Left arrow.
          sendString("\u001b[D");
          break;
        case 0x1000004: // Right arrow.
          sendString("\u001b[C");
          break;
        case 0x1000005: // PgUp key.
          sendString("\u001b[5~");
          break;
        case 0x1000006: // PgDn key.
          sendString("\u001b[6~");
          break;
        case 0x1000007: // Home key.
          sendString("\u001b[H");
          break;
        case 0x1000008: // End key.
          sendString("\u001b[F");
          break;
        case 0x1000009: // Insert.
          sendString("\u001b[2~");
          break;
        case 0x100000a: // F1 key.
          if ((event.stateMask & SWT.CTRL) != 0) {
            // Allow Ctrl+F1 to act locally as well as on the remote, because it is typically non-intrusive
            event.doit = true;
          }
          sendString("\u001b[M");
          break;
        case 0x100000b: // F2 key.
          sendString("\u001b[N");
          break;
        case 0x100000c: // F3 key.
          sendString("\u001b[O");
          break;
        case 0x100000d: // F4 key.
          sendString("\u001b[P");
          break;
        case 0x100000e: // F5 key.
          sendString("\u001b[Q");
          break;
        case 0x100000f: // F6 key.
          sendString("\u001b[R");
          break;
        case 0x1000010: // F7 key.
          sendString("\u001b[S");
          break;
        case 0x1000011: // F8 key.
          sendString("\u001b[T");
          break;
        case 0x1000012: // F9 key.
          sendString("\u001b[U");
          break;
        case 0x1000013: // F10 key.
          sendString("\u001b[V");
          break;
        case 0x1000014: // F11 key.
          sendString("\u001b[W");
          break;
        case 0x1000015: // F12 key.
          sendString("\u001b[X");
          break;
        default:
          // Ignore other special keys. Control flows through this case when the user presses SHIFT, CONTROL, ALT, and
          // any other key not handled by the above cases.
          break;
        }
        // It's ok to return here, because we never locally echo special keys.
        return;
      }
      // To fix SPR 110341, we consider the Alt key to be pressed only when the Control key is _not_ also pressed. This
      // works around a bug in SWT where, on European keyboards, the AltGr key being pressed appears to us as Control
      // + Alt being pressed simultaneously.
      Logger.log("stateMask = " + event.stateMask);
      boolean altKeyPressed = (((event.stateMask & SWT.ALT) != 0) && ((event.stateMask & SWT.CTRL) == 0));
      if (!altKeyPressed && (event.stateMask & SWT.CTRL) != 0 && character == ' ') {
        // Send a NUL character -- many terminal emulators send NUL when Control-Space is pressed. This is used to set
        // the mark in Emacs.
        character = '\u0000';
      }
      sendChar(character, altKeyPressed);
      // Special case: When we are in a TCP connection and echoing characters locally, send a LF after sending a CR.
      // ISSUE: Is this absolutely required?
      if (character == '\r' && getTerminalConnector() != null && isConnected() && getTerminalConnector().isLocalEcho()) {
        sendChar('\n', false);
      }
      // Now decide if we should locally echo the character we just sent. We do _not_ locally echo the character if any
      // of these conditions are true:
      //
      // * This is a serial connection.
      // * This is a TCP connection (i.e., m_telnetConnection is not null) and the remote endpoint is not a TELNET
      //   server.
      // * The ALT (or META) key is pressed.
      // * The character is any of the first 32 ISO Latin-1 characters except Control-I or Control-M.
      // * The character is the DELETE character.
      if (getTerminalConnector() == null || getTerminalConnector().isLocalEcho() == false || altKeyPressed
          || (character >= '\u0001' && character < '\t') || (character > '\t' && character < '\r')
          || (character > '\r' && character <= '\u001f') || character == '\u007f') {
        // No local echoing.
        return;
      }
      // Locally echo the character.
      StringBuilder charBuffer = new StringBuilder();
      charBuffer.append(character);
      // If the character is a carriage return, we locally echo it as a CR + LF combination.
      if (character == '\r') {
        charBuffer.append('\n');
      }
      writeToTerminal(charBuffer.toString());
    }
  }

  @Override public void setTerminalTitle(String title) {
    terminalListener.setTerminalTitle(title);
  }

  @Override public TerminalState getState() {
    return state;
  }

  @Override public void setState(TerminalState state) {
    this.state = state;
    terminalListener.setState(state);
    // enable the (blinking) cursor if the terminal is connected
    runAsyncInDisplayThread(new Runnable() {
      @Override public void run() {
        if (textControl != null && !textControl.isDisposed()) {
          textControl.setCursorEnabled(isConnected());
        }
      }
    });
  }

  private void runAsyncInDisplayThread(Runnable runnable) {
    if (Display.findDisplay(Thread.currentThread()) != null) {
      runnable.run();
    } else if (PlatformUI.isWorkbenchRunning()) {
      PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
      // else should not happen and we ignore it...
    }
  }

  @Override public String getSettingsSummary() {
    if (getTerminalConnector() != null) {
      return getTerminalConnector().getSettingsSummary();
    }
    return "";
  }

  @Override public void setConnector(ITerminalConnector connector) {
    this.connector = connector;
  }

  @Override public ICommandInputField getCommandInputField() {
    return commandInputField;
  }

  @Override public void setCommandInputField(ICommandInputField inputField) {
    if (commandInputField != null) {
      commandInputField.dispose();
    }
    commandInputField = inputField;
    if (commandInputField != null) {
      commandInputField.createControl(rootControl, this);
    }
    if (rootControl.isVisible()) {
      rootControl.layout(true);
    }
  }

  @Override public int getBufferLineLimit() {
    return terminalModel.getMaxHeight();
  }

  @Override public void setBufferLineLimit(int bufferLineLimit) {
    if (bufferLineLimit <= 0) {
      return;
    }
    synchronized (terminalModel) {
      if (terminalModel.getHeight() > bufferLineLimit) {
        terminalModel.setDimensions(bufferLineLimit, terminalModel.getWidth());
      }
      terminalModel.setMaxHeight(bufferLineLimit);
    }
  }

  @Override public boolean isScrollLockOn() {
    return textControl.isScrollLockOn();
  }

  @Override public void setScrollLockOn(boolean on) {
    textControl.setScrollLockOn(on);
  }

  @Override public void setInvertedColors(boolean invert) {
    textControl.setInvertedColors(invert);
  }

  public void setColors(RGB background, RGB foreground) {
    textControl.setColors(background, foreground);
  }

  public void setBlinkingCursor(boolean useBlinkingCursor) {
    textControl.setBlinkingCursor(useBlinkingCursor);
  }
}
