/*******************************************************************************
 * 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
 *
 * Initial Contributors:
 * The following Wind River employees contributed to the Terminal component
 * that contains this file: Chris Thew, Fran Litterio, Stephen Lamb,
 * Helmut Haigermoser and Ted Williams.
 *
 * Contributors:
 * Michael Scharf (Wind River) - split into core, view and connector plugins
 * Martin Oberhuber (Wind River) - fixed copyright headers and beautified
 * Martin Oberhuber (Wind River) - [206892] State handling: Only allow connect when CLOSED
 * Martin Oberhuber (Wind River) - [206883] Serial Terminal leaks Jobs
 * Martin Oberhuber (Wind River) - [208145] Terminal prints garbage after quick disconnect/reconnect
 * Martin Oberhuber (Wind River) - [207785] NPE when trying to send char while no longer connected
 * Michael Scharf (Wind River) - [209665] Add ability to log byte streams from terminal
 * Ruslan Sychev (Xored Software) - [217675] NPE or SWTException when closing Terminal View while connection establishing
 * Michael Scharf (Wing River) - [196447] The optional terminal input line should be resizeable
 * Martin Oberhuber (Wind River) - [168197] Replace JFace MessagDialog by SWT MessageBox
 * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use
 * Michael Scharf (Wind River) - [237398] Terminal get Invalid Thread Access when the title is set
 * Martin Oberhuber (Wind River) - [240745] Pressing Ctrl+F1 in the Terminal should bring up context help
 * Michael Scharf (Wind River) - [240098] The cursor should not blink when the terminal is disconnected
 * Anton Leherbauer (Wind River) - [335021] Middle mouse button copy/paste does not work with the terminal
 * Max Stepanov (Appcelerator) - [339768] Fix ANSI code for PgUp / PgDn
 * Pawel Piech (Wind River) - [333613] "Job found still running" after shutdown
 * Martin Oberhuber (Wind River) - [348700] Terminal unusable after disconnect
 * Simon Bernard (Sierra Wireless) - [351424] [terminal] Terminal does not support del and insert key
 *******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;

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.tm.internal.terminal.control.*;
import org.eclipse.tm.internal.terminal.control.impl.*;
import org.eclipse.tm.internal.terminal.provisional.api.*;
import org.eclipse.tm.internal.terminal.textcanvas.*;
import org.eclipse.tm.internal.terminal.textcanvas.PipedInputStream;
import org.eclipse.tm.terminal.model.*;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.*;
import org.eclipse.ui.keys.IBindingService;

/**
 *
 * This class was originally written to use nested classes, which unfortunately makes
 * this source file larger and more complex than it needs to be.  In particular, the
 * methods in the nested classes directly access the fields of the enclosing class.
 * One day we should pull the nested classes out into their own source files (but still
 * in this package).
 *
 * @author Chris Thew <chris.thew@windriver.com>
 */
public class VT100TerminalControl implements ITerminalControlForText, ITerminalControl, ITerminalViewControl
{
    protected final static String[] LINE_DELIMITERS = { "\n" }; //$NON-NLS-1$

    /**
     * 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			  fTerminalText;
    private Display                   fDisplay;
    private TextCanvas                fCtlText;
    private Composite                 fWndParent;
    private Clipboard                 fClipboard;
    private KeyListener               fKeyHandler;
    private final ITerminalListener         fTerminalListener;
    private String                    fMsg = ""; //$NON-NLS-1$
    private FocusListener             fFocusListener;
    private ITerminalConnector		  fConnector;
    private final ITerminalConnector[]      fConnectors;
    PipedInputStream fInputStream;
	private static final String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
	private String fEncoding = defaultEncoding;
	private InputStreamReader fInputStreamReader;

	private ICommandInputField fCommandInputField;

	private volatile TerminalState fState;

	private final ITerminalTextData fTerminalModel;

	/**
	 * Is protected by synchronize on this
	 */
	volatile private Job fJob;

	public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
		fConnectors=connectors;
		fTerminalListener=target;
		fTerminalModel=TerminalTextDataFactory.makeTerminalTextData();
		fTerminalModel.setMaxHeight(1000);
		fInputStream=new PipedInputStream(8*1024);
		fTerminalText = new VT100Emulator(fTerminalModel, this, null);
		try {
			// Use Default Encoding as start, until setEncoding() is called
			setEncoding(null);
		} catch (UnsupportedEncodingException e) {
			// Should never happen
			e.printStackTrace();
			// Fall back to local Platform Default Encoding
			fEncoding = defaultEncoding;
			fInputStreamReader = new InputStreamReader(fInputStream);
			fTerminalText.setInputStreamReader(fInputStreamReader);
		}

		setupTerminal(wndParent);
	}

	@Override public void setEncoding(String encoding) throws UnsupportedEncodingException {
		if (encoding == null) {
			// TODO better use a standard remote-to-local encoding?
			encoding = "ISO-8859-1"; //$NON-NLS-1$
			// TODO or better use the local default encoding?
			// encoding = defaultEncoding;
		}
		fInputStreamReader = new InputStreamReader(fInputStream, encoding);
		// remember encoding if above didn't throw an exception
		fEncoding = encoding;
		fTerminalText.setInputStreamReader(fInputStreamReader);
	}

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

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

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#copy()
	 */
	@Override public void copy() {
		copy(DND.CLIPBOARD);
	}

	private void copy(int clipboardType) {
		Object[] data = new Object[] { getSelection() };
		Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
		fClipboard.setContents(data, types, clipboardType);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#paste()
	 */
	@Override public void paste() {
		paste(DND.CLIPBOARD);
// TODO paste in another thread.... to avoid blocking
//		new Thread() {
//			public void run() {
//				for (int i = 0; i < strText.length(); i++) {
//					sendChar(strText.charAt(i), false);
//				}
//
//			}
//		}.start();
	}

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

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

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#selectAll()
	 */
	@Override public void selectAll() {
		getCtlText().selectAll();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#sendKey(char)
	 */
	@Override public void sendKey(char character) {
		Event event;
		KeyEvent keyEvent;

		event = new Event();
		event.widget = getCtlText();
		event.character = character;
		event.keyCode = 0;
		event.stateMask = 0;
		event.doit = true;
		keyEvent = new KeyEvent(event);

		fKeyHandler.keyPressed(keyEvent);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#clearTerminal()
	 */
	@Override public void clearTerminal() {
		// The TerminalText object does all text manipulation.

		getTerminalText().clearTerminal();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getClipboard()
	 */
	@Override public Clipboard getClipboard() {
		return fClipboard;
	}

	/**
	 * @return non null selection
	 */
	@Override public String getSelection() {
		String txt= fCtlText.getSelectionText();
		if(txt==null)
     {
      txt=""; //$NON-NLS-1$
    }
		return txt;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setFocus()
	 */
	@Override public boolean setFocus() {
		return getCtlText().setFocus();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isEmpty()
	 */
	@Override public boolean isEmpty() {
		return getCtlText().isEmpty();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isDisposed()
	 */
	@Override public boolean isDisposed() {
		return getCtlText().isDisposed();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isConnected()
	 */
	@Override public boolean isConnected() {
		return fState==TerminalState.CONNECTED;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disposeTerminal()
	 */
	@Override public void disposeTerminal() {
		Logger.log("entered."); //$NON-NLS-1$
		disconnectTerminal();
		fClipboard.dispose();
		getTerminalText().dispose();
	}

	@Override public void connectTerminal() {
		Logger.log("entered."); //$NON-NLS-1$
		if(getTerminalConnector()==null) {
      return;
    }
		fTerminalText.resetState();
		if(fConnector.getInitializationErrorMessage()!=null) {
			showErrorMessage(NLS.bind(
					TerminalMessages.CannotConnectTo,
					fConnector.getName(),
					fConnector.getInitializationErrorMessage()));
			// we cannot connect because the connector was not initialized
			return;
		}
		getTerminalConnector().connect(this);
		// clean the error message
		setMsg(""); //$NON-NLS-1$
		waitForConnect();
	}

	@Override public ITerminalConnector getTerminalConnector() {
		return fConnector;
	}
	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disconnectTerminal()
	 */
	@Override public void disconnectTerminal() {
		Logger.log("entered."); //$NON-NLS-1$

		//Disconnect the remote side first
		if (getState()!=TerminalState.CLOSED) {
			if(getTerminalConnector()!=null) {
				getTerminalConnector().disconnect();
			}
		}

        //Ensure that a new Job can be started; then clean up old Job.
        Job job;
        synchronized(this) {
            job = fJob;
            fJob = null;
        }
        if (job!=null) {
            job.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 = job.getThread();
            if(t!=null) {
              t.interrupt();
            }
            try {
                job.join();
            } catch (InterruptedException e) {}
        }
	}

	// TODO
	private void waitForConnect() {
		Logger.log("entered."); //$NON-NLS-1$
		// TODO
		// Eliminate this code
		while (getState()==TerminalState.CONNECTING) {
			if (fDisplay.readAndDispatch()) {
        continue;
      }

			fDisplay.sleep();
		}
		if(getCtlText().isDisposed()) {
			disconnectTerminal();
			return;
		}
		if (!getMsg().equals("")) //$NON-NLS-1$
		{
			showErrorMessage(getMsg());

			disconnectTerminal();
			return;
		}
		getCtlText().setFocus();
		startReaderJob();

	}

	private synchronized void startReaderJob() {
		if(fJob==null) {
			fJob=new Job("Terminal data reader") { //$NON-NLS-1$
				@Override protected IStatus run(IProgressMonitor monitor) {
					IStatus status=Status.OK_STATUS;
					try {
						while(true) {
							while(fInputStream.available()==0 && !monitor.isCanceled()) {
								try {
									fInputStream.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!
								fTerminalText.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 (fJob==this) {
								fJob=null;
							}
						}
					}
					return status;
				}

			};
			fJob.setSystem(true);
			fJob.schedule();
		}
	}

	private void showErrorMessage(String message) {
		String strTitle = TerminalMessages.TerminalError;
		// [168197] Replace JFace MessagDialog by SWT MessageBox
		//MessageDialog.openError( getShell(), strTitle, message);
		MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK);
		mb.setText(strTitle);
		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(fEncoding));
			getOutputStream().flush();
		} catch (SocketException socketException) {
			displayTextInTerminal(socketException.getMessage());

			String strMsg = TerminalMessages.SocketError
					+ "!\n" + socketException.getMessage(); //$NON-NLS-1$
			showErrorMessage(strMsg);

			Logger.logException(socketException);

			disconnectTerminal();
		} catch (IOException ioException) {
			showErrorMessage(TerminalMessages.IOError + "!\n" + ioException.getMessage());//$NON-NLS-1$

			Logger.logException(ioException);

			disconnectTerminal();
		}
	}

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

	protected void sendChar(char chKey, boolean altKeyPressed) {
		try {
			int byteToSend = chKey;
			OutputStream os = getOutputStream();
			if (os==null) {
				// Bug 207785: NPE when trying to send char while no longer connected
				Logger.log("NOT sending '" + byteToSend + "' because no longer connected"); //$NON-NLS-1$ //$NON-NLS-2$
			} 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 + '" + byteToSend + "'"); //$NON-NLS-1$ //$NON-NLS-2$
					getOutputStream().write('\u001b');
					getOutputStream().write(byteToSend);
				} else {
					Logger.log("sending '" + byteToSend + "'"); //$NON-NLS-1$ //$NON-NLS-2$
					getOutputStream().write(byteToSend);
				}
				getOutputStream().flush();
			}
		} catch (SocketException socketException) {
			Logger.logException(socketException);

			displayTextInTerminal(socketException.getMessage());

			String strMsg = TerminalMessages.SocketError
					+ "!\n" + socketException.getMessage(); //$NON-NLS-1$

			showErrorMessage(strMsg);
			Logger.logException(socketException);

			disconnectTerminal();
		} catch (IOException ioException) {
			Logger.logException(ioException);

			displayTextInTerminal(ioException.getMessage());

			String strMsg = TerminalMessages.IOError + "!\n" + ioException.getMessage(); //$NON-NLS-1$

			showErrorMessage(strMsg);
			Logger.logException(ioException);

			disconnectTerminal();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setupTerminal(org.eclipse.swt.widgets.Composite)
	 */
	@Override public void setupTerminal(Composite parent) {
		Assert.isNotNull(parent);
		fState=TerminalState.CLOSED;
		setupControls(parent);
		setupListeners();
		setupHelp(fWndParent, TerminalPlugin.HELP_VIEW);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#onFontChanged()
	 */
	@Override public void setFont(Font font) {
		getCtlText().setFont(font);
		if(fCommandInputField!=null) {
			fCommandInputField.setFont(font);
		}

		// Tell the TerminalControl singleton that the font has changed.
		fCtlText.onFontChange();
		getTerminalText().fontChanged();
	}
	@Override public Font getFont() {
		return getCtlText().getFont();
	}
	@Override public Control getControl() {
		return fCtlText;
	}
	@Override public Control getRootControl() {
		return fWndParent;
	}
	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().

		fWndParent=new Composite(parent,SWT.NONE);
		GridLayout layout=new GridLayout();
		layout.marginWidth=0;
		layout.marginHeight=0;
		layout.verticalSpacing=0;
		fWndParent.setLayout(layout);

		ITerminalTextDataSnapshot snapshot=fTerminalModel.makeSnapshot();
		// TODO how to get the initial size correctly!
		snapshot.updateSnapshot(false);
		ITextCanvasModel canvasModel=new PollingTextCanvasModel(snapshot);
		fCtlText=new TextCanvas(fWndParent,canvasModel,SWT.NONE,new TextLineRenderer(fCtlText,canvasModel));
		fCtlText.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseUp(MouseEvent e) {
        IHyperlink hyperlink = hyperlinkAt(e);
        if (hyperlink != null) {
          hyperlink.open();
        }
      }
    });
    fCtlText.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 = fCtlText.getDisplay().getSystemCursor(cursorId);
        if (!newCursor.equals(fCtlText.getCursor())) {
          fCtlText.setCursor(newCursor);
        }
      }
    });

		fCtlText.setLayoutData(new GridData(GridData.FILL_BOTH));
		fCtlText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		fCtlText.addResizeHandler(new TextCanvas.ResizeListener() {
			@Override public void sizeChanged(int lines, int columns) {
				fTerminalText.setDimensions(lines, columns);
			}
		});
		fCtlText.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);
				}
			}
		});

		fDisplay = getCtlText().getDisplay();
		fClipboard = new Clipboard(fDisplay);
//		fViewer.setDocument(new TerminalDocument());
		setFont(JFaceResources.getTextFont());
	}

  private IHyperlink hyperlinkAt(MouseEvent e) {
    Point p = fCtlText.screenPointToCell(e.x, e.y);
    if (p != null) {
      List<IHyperlink> hyperlinks = fTerminalText.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() {
		fKeyHandler = new TerminalKeyHandler();
		fFocusListener = new TerminalFocusListener();

		getCtlText().addKeyListener(fKeyHandler);
		getCtlText().addFocusListener(fFocusListener);

	}

	/**
	 * Setup all the help contexts for the controls.
	 */
	protected void setupHelp(Composite parent, String id) {
		Control[] children = parent.getChildren();

		for (int nIndex = 0; nIndex < children.length; nIndex++) {
			if (children[nIndex] instanceof Composite) {
				setupHelp((Composite) children[nIndex], id);
			}
		}

		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, id);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#displayTextInTerminal(java.lang.String)
	 */
	@Override public void displayTextInTerminal(String text) {
		writeToTerminal("\r\n"+text+"\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
	}
	private void writeToTerminal(String text) {
		try {
			getRemoteToTerminalOutputStream().write(text.getBytes(fEncoding));
		} 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(fInputStream.getOutputStream());
		} else {
			return fInputStream.getOutputStream();
		}
	}
	protected boolean isLogCharEnabled() {
		return TerminalPlugin.isOptionEnabled(Logger.TRACE_DEBUG_LOG_CHAR);
	}
	protected boolean isLogBufferSizeEnabled() {
		return TerminalPlugin
				.isOptionEnabled(Logger.TRACE_DEBUG_LOG_BUFFER_SIZE);
	}


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

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setMsg(java.lang.String)
	 */
	@Override public void setMsg(String msg) {
		fMsg = msg;
	}

	public String getMsg() {
		return fMsg;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getCtlText()
	 */
	protected TextCanvas getCtlText() {
		return fCtlText;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getTerminalText()
	 */
	public VT100Emulator getTerminalText() {
		return fTerminalText;
	}
	protected class TerminalFocusListener implements FocusListener {
		private IContextActivation contextActivation = null;

		protected TerminalFocusListener() {
			super();
		}

		@Override public void focusGained(FocusEvent event) {
			// Disable all keyboard accelerators (e.g., Control-B) so the Terminal view
			// can see every keystroke.  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("org.eclipse.tm.terminal.TerminalContext"); //$NON-NLS-1$
		}

		@Override public void focusLost(FocusEvent event) {
			// Enable all keybindings.

			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;
      }

			// 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 (!isConnected()) {
			if (fState==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~"); //$NON-NLS-1$
				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"); //$NON-NLS-1$
					break;

				case 0x1000002: // Down arrow.
					sendString("\u001b[B"); //$NON-NLS-1$
					break;

				case 0x1000003: // Left arrow.
					sendString("\u001b[D"); //$NON-NLS-1$
					break;

				case 0x1000004: // Right arrow.
					sendString("\u001b[C"); //$NON-NLS-1$
					break;

				case 0x1000005: // PgUp key.
					sendString("\u001b[5~"); //$NON-NLS-1$
					break;

				case 0x1000006: // PgDn key.
					sendString("\u001b[6~"); //$NON-NLS-1$
					break;

				case 0x1000007: // Home key.
					sendString("\u001b[H"); //$NON-NLS-1$
					break;

				case 0x1000008: // End key.
					sendString("\u001b[F"); //$NON-NLS-1$
					break;

				case 0x1000009: // Insert.
					sendString("\u001b[2~"); //$NON-NLS-1$
					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"); //$NON-NLS-1$
					break;

				case 0x100000b: // F2 key.
					sendString("\u001b[N"); //$NON-NLS-1$
					break;

				case 0x100000c: // F3 key.
					sendString("\u001b[O"); //$NON-NLS-1$
					break;

				case 0x100000d: // F4 key.
					sendString("\u001b[P"); //$NON-NLS-1$
					break;

				case 0x100000e: // F5 key.
					sendString("\u001b[Q"); //$NON-NLS-1$
					break;

				case 0x100000f: // F6 key.
					sendString("\u001b[R"); //$NON-NLS-1$
					break;

				case 0x1000010: // F7 key.
					sendString("\u001b[S"); //$NON-NLS-1$
					break;

				case 0x1000011: // F8 key.
					sendString("\u001b[T"); //$NON-NLS-1$
					break;

				case 0x1000012: // F9 key.
					sendString("\u001b[U"); //$NON-NLS-1$
					break;

				case 0x1000013: // F10 key.
					sendString("\u001b[V"); //$NON-NLS-1$
					break;

				case 0x1000014: // F11 key.
					sendString("\u001b[W"); //$NON-NLS-1$
					break;

				case 0x1000015: // F12 key.
					sendString("\u001b[X"); //$NON-NLS-1$
					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); //$NON-NLS-1$

			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:
			//
			// o This is a serial connection.
			//
			// o This is a TCP connection (i.e., m_telnetConnection is not null) and
			//   the remote endpoint is not a TELNET server.
			//
			// o The ALT (or META) key is pressed.
			//
			// o The character is any of the first 32 ISO Latin-1 characters except
			//   Control-I or Control-M.
			//
			// o 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.

			StringBuffer charBuffer = new StringBuffer();
			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) {
		fTerminalListener.setTerminalTitle(title);
	}


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


	@Override public void setState(TerminalState state) {
		fState=state;
		fTerminalListener.setState(state);
		// enable the (blinking) cursor if the terminal is connected
		runAsyncInDisplayThread(new Runnable() {
			@Override public void run() {
				if(fCtlText!=null && !fCtlText.isDisposed()) {
          fCtlText.setCursorEnabled(isConnected());
        }
			}});
	}
	/**
	 * @param runnable run in display thread
	 */
	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 ""; //$NON-NLS-1$
	}

	@Override public void setConnector(ITerminalConnector connector) {
		fConnector=connector;

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

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

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

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

	@Override public boolean isScrollLock() {
		return fCtlText.isScrollLock();
	}

	@Override public void setScrollLock(boolean on) {
		fCtlText.setScrollLock(on);
	}

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

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