/*******************************************************************************
 * 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 org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.resource.JFaceResources;
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);
	}

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

	public String getEncoding() {
		return fEncoding;
	}

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

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#copy()
	 */
	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()
	 */
	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
	 */
	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()
	 */
	public void selectAll() {
		getCtlText().selectAll();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#sendKey(char)
	 */
	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()
	 */
	public void clearTerminal() {
		// The TerminalText object does all text manipulation.

		getTerminalText().clearTerminal();
	}

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

	/**
	 * @return non null selection
	 */
	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()
	 */
	public boolean setFocus() {
		return getCtlText().setFocus();
	}

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

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

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

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

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

	public ITerminalConnector getTerminalConnector() {
		return fConnector;
	}
	/* (non-Javadoc)
	 * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disconnectTerminal()
	 */
	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$
				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();
		}
	}

	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)
	 */
	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()
	 */
	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();
	}
	public Font getFont() {
		return getCtlText().getFont();
	}
	public Control getControl() {
		return fCtlText;
	}
	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.setLayoutData(new GridData(GridData.FILL_BOTH));
		fCtlText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		fCtlText.addResizeHandler(new TextCanvas.ResizeListener() {
			public void sizeChanged(int lines, int columns) {
				fTerminalText.setDimensions(lines, columns);
			}
		});
		fCtlText.addMouseListener(new MouseAdapter() {
			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());
	}

	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)
	 */
	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();
		}

	}

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


	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)
	 */
	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();
		}

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

		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 {
		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());
		}

	}

	public void setTerminalTitle(String title) {
		fTerminalListener.setTerminalTitle(title);
	}


	public TerminalState getState() {
		return fState;
	}


	public void setState(TerminalState state) {
		fState=state;
		fTerminalListener.setState(state);
		// enable the (blinking) cursor if the terminal is connected
		runAsyncInDisplayThread(new Runnable() {
			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...
    }
	}

	public String getSettingsSummary() {
		if(getTerminalConnector()!=null) {
      return getTerminalConnector().getSettingsSummary();
    }
		return ""; //$NON-NLS-1$
	}

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

	}
	public ICommandInputField getCommandInputField() {
		return fCommandInputField;
	}

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

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

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

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

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

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

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