TERMINAL: support multiple log saving function by tab.
authorJaeMin Kim <jm.jemin.kim@samsung.com>
Mon, 15 May 2017 05:01:02 +0000 (14:01 +0900)
committerJaeMin Kim <jm.jemin.kim@samsung.com>
Thu, 18 May 2017 10:19:13 +0000 (19:19 +0900)
Support multiple log saving function by tab.

Change-Id: I5987625e63095a5a58b7be178e96eb051c40772a
Signed-off-by: JaeMin Kim <jm.jemin.kim@samsung.com>
13 files changed:
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.connector.serial/src/org/eclipse/tm/terminal/connector/serial/connector/SerialConnector.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.connector.serial/src/org/eclipse/tm/terminal/connector/serial/connector/SerialPortHandler.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/connector/TerminalConnector.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/control/ITerminalViewControl.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/control/SaveLogOutputStream.java [new file with mode: 0644]
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalConnector.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/provisional/api/provider/TerminalConnectorImpl.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/tabs/TabDisposeListener.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/tabs/TabFolderManager.java
rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/tabs/ToggleSaveLogHandler.java [new file with mode: 0644]
rt-ide/tizen.rt.terminalex.plugin/META-INF/MANIFEST.MF
rt-ide/tizen.rt.terminalex.plugin/src/org/tizen/rt/ide/terminal/view/ui/tabs/ToggleSaveLogAction.java

index 695181c..a52ce53 100644 (file)
@@ -39,207 +39,226 @@ import gnu.io.CommPortIdentifier;
 import gnu.io.SerialPort;
 
 public class SerialConnector extends TerminalConnectorImpl {
-       private OutputStream fOutputStream;
-       private InputStream fInputStream;
-       private SerialPort fSerialPort;
+    private OutputStream fOutputStream;
+    private InputStream fInputStream;
+    private SerialPort fSerialPort;
     private CommPortIdentifier fSerialPortIdentifier;
-       private SerialPortHandler fTerminalSerialPortHandler;
-       private SerialSettings fSettings;
-       private SerialConnectWorker fConnectWorker = null;
-       /* default */ volatile boolean fDisconnectGoingOn = false;
-
-       public SerialConnector() {
-       }
-       @Override
+    private SerialPortHandler fTerminalSerialPortHandler;
+    private SerialSettings fSettings;
+    private SerialConnectWorker fConnectWorker = null;
+    /* default */ volatile boolean fDisconnectGoingOn = false;
+
+    public SerialConnector() {
+    }
+
+    @Override
     public void initialize() throws Exception {
-               try {
-                       fSettings=new SerialSettings();
-               } catch (NoClassDefFoundError e) {
-                       // tell the user how to install the library
-                       throw new CoreException(new Status(IStatus.WARNING,UIPlugin.getUniqueIdentifier(),0, Messages.SerialConnector_Error_LiberayNotInstalled,e));
-               }
-       }
-       @Override
+        try {
+            fSettings = new SerialSettings();
+        } catch (NoClassDefFoundError e) {
+            // tell the user how to install the library
+            throw new CoreException(new Status(IStatus.WARNING, UIPlugin.getUniqueIdentifier(), 0, Messages.SerialConnector_Error_LiberayNotInstalled, e));
+        }
+    }
+
+    @Override
     public void connect(ITerminalControl control) {
-               super.connect(control);
-               synchronized(this) {
-                       if (fConnectWorker!=null || fDisconnectGoingOn) {
-                               //avoid multiple background connect/disconnect threads at the same time
-                               return;
-                       }
-                       fConnectWorker = new SerialConnectWorker(this, control);
-               }
-               fControl.setState(TerminalState.CONNECTING);
-               fConnectWorker.start();
-       }
-       /**
-        * Indicate that the connectWorker is finished.
-        */
-       void doneConnect() {
-               synchronized(this) {
-                       fConnectWorker = null;
-               }
-       }
-       @Override
+        super.connect(control);
+        synchronized (this) {
+            if (fConnectWorker != null || fDisconnectGoingOn) {
+                // avoid multiple background connect/disconnect threads at the same time
+                return;
+            }
+            fConnectWorker = new SerialConnectWorker(this, control);
+        }
+        fControl.setState(TerminalState.CONNECTING);
+        fConnectWorker.start();
+    }
+
+    /**
+     * Indicate that the connectWorker is finished.
+     */
+    void doneConnect() {
+        synchronized (this) {
+            fConnectWorker = null;
+        }
+    }
+
+    @Override
     public void doDisconnect() {
-               synchronized(this) {
-                       //avoid multiple background connect/disconnect threads at the same time
-                       if (fConnectWorker!=null) {
-                               fConnectWorker.interrupt();
-                               return;
-                       } else if (fDisconnectGoingOn) {
-                               return;
-                       }
-                       fDisconnectGoingOn = true;
-               }
-
-               // Fix for SPR 112422.  When output is being received from the serial port, the
-               // below call to removePortOwnershipListener() attempts to lock the serial port
-               // object, but that object is already locked by another Terminal view thread
-               // waiting for the SWT display thread to process a syncExec() call.  Since this
-               // method is called on the display thread, the display thread is waiting to
-               // lock the serial port object and the thread holding the serial port object
-               // lock is waiting for the display thread to process a syncExec() call, so the
-               // two threads end up deadlocked, which hangs the Workbench GUI.
-               //
-               // The solution is to spawn a short-lived worker thread that calls
-               // removePortOwnershipListener(), thus preventing the display thread from
-               // deadlocking with the other Terminal view thread.
-
-               new Thread("Terminal View Serial Port Disconnect Worker") //$NON-NLS-1$
-               {
-                       @Override
+        synchronized (this) {
+            // avoid multiple background connect/disconnect threads at the same time
+            if (fConnectWorker != null) {
+                fConnectWorker.interrupt();
+                return;
+            } else if (fDisconnectGoingOn) {
+                return;
+            }
+            fDisconnectGoingOn = true;
+        }
+
+        // Fix for SPR 112422. When output is being received from the serial port, the
+        // below call to removePortOwnershipListener() attempts to lock the serial port
+        // object, but that object is already locked by another Terminal view thread
+        // waiting for the SWT display thread to process a syncExec() call. Since this
+        // method is called on the display thread, the display thread is waiting to
+        // lock the serial port object and the thread holding the serial port object
+        // lock is waiting for the display thread to process a syncExec() call, so the
+        // two threads end up deadlocked, which hangs the Workbench GUI.
+        //
+        // The solution is to spawn a short-lived worker thread that calls
+        // removePortOwnershipListener(), thus preventing the display thread from
+        // deadlocking with the other Terminal view thread.
+
+        new Thread("Terminal View Serial Port Disconnect Worker") //$NON-NLS-1$
+        {
+            @Override
             public void run() {
-                               try {
-                                       if (getSerialPortIdentifier() != null) {
-                                               try {
-                                                       getSerialPortIdentifier()
-                                                               .removePortOwnershipListener(getSerialPortHandler());
-                                               } catch(Exception e) {
-                                                       Logger.logException(e);
-                                               }
-                                       }
-
-                                       if (getSerialPort() != null) {
-                                               //Event listener is removed as part of close(),
-                                               //but exceptions need to be caught to ensure that close() really succeeds
-                                               try {
-                                                       getSerialPort().removeEventListener();
-                                                       Thread.sleep(50); //allow a little time for RXTX Native to catch up - makes stuff more stable
-                                               } catch(Exception e) {
-                                                       Logger.logException(e);
-                                               }
-                                               Logger.log("Calling close() on serial port ..."); //$NON-NLS-1$
-                                               getSerialPort().close();
-                                       }
-
-                                       if (getInputStream() != null) {
-                                               try {
-                                                       getInputStream().close();
-                                               } catch (Exception exception) {
-                                                       Logger.logException(exception);
-                                               }
-                                       }
-
-                                       if (getTerminalToRemoteStream() != null) {
-                                               try {
-                                                       getTerminalToRemoteStream().close();
-                                               } catch (Exception exception) {
-                                                       Logger.logException(exception);
-                                               }
-                                       }
-
-                                       setSerialPortIdentifier(null);
-                                       cleanSerialPort();
-                                       setSerialPortHandler(null);
-                               } catch(Exception e) {
-                                       Logger.logException(e);
-                               } finally {
-                                       fDisconnectGoingOn = false;
-                               }
-                       }
-
-               }.start();
-       }
-       public InputStream getInputStream() {
-               return fInputStream;
-       }
-       @Override
+                try {
+                    if (getSerialPortIdentifier() != null) {
+                        try {
+                            getSerialPortIdentifier()
+                                    .removePortOwnershipListener(getSerialPortHandler());
+                        } catch (Exception e) {
+                            Logger.logException(e);
+                        }
+                    }
+
+                    if (getSerialPort() != null) {
+                        // Event listener is removed as part of close(),
+                        // but exceptions need to be caught to ensure that close() really succeeds
+                        try {
+                            getSerialPort().removeEventListener();
+                            Thread.sleep(50); // allow a little time for RXTX Native to catch up - makes stuff more stable
+                        } catch (Exception e) {
+                            Logger.logException(e);
+                        }
+                        Logger.log("Calling close() on serial port ..."); //$NON-NLS-1$
+                        getSerialPort().close();
+                    }
+
+                    if (getInputStream() != null) {
+                        try {
+                            getInputStream().close();
+                        } catch (Exception exception) {
+                            Logger.logException(exception);
+                        }
+                    }
+
+                    if (getTerminalToRemoteStream() != null) {
+                        try {
+                            getTerminalToRemoteStream().close();
+                        } catch (Exception exception) {
+                            Logger.logException(exception);
+                        }
+                    }
+
+                    setSerialPortIdentifier(null);
+                    cleanSerialPort();
+                    setSerialPortHandler(null);
+                } catch (Exception e) {
+                    Logger.logException(e);
+                } finally {
+                    fDisconnectGoingOn = false;
+                }
+            }
+
+        }.start();
+    }
+
+    public InputStream getInputStream() {
+        return fInputStream;
+    }
+
+    @Override
     public OutputStream getTerminalToRemoteStream() {
-               return fOutputStream;
-       }
-       private void setInputStream(InputStream inputStream) {
-               fInputStream = inputStream;
-       }
-       private void setOutputStream(OutputStream outputStream) {
-               fOutputStream = outputStream;
-       }
-       @Override
+        return fOutputStream;
+    }
+
+    private void setInputStream(InputStream inputStream) {
+        fInputStream = inputStream;
+    }
+
+    private void setOutputStream(OutputStream outputStream) {
+        fOutputStream = outputStream;
+    }
+
+    @Override
     public void setTerminalSize(int newWidth, int newHeight) {
-               // TODO
-       }
-       protected SerialPort getSerialPort() {
-               return fSerialPort;
-       }
-
-       /**
-        * sets the socket to null
-        */
-       void cleanSerialPort() {
-               fSerialPort=null;
-               setInputStream(null);
-               setOutputStream(null);
-       }
-
-       protected void setSerialPort(SerialPort serialPort) throws IOException {
-               cleanSerialPort();
-               if(serialPort!=null) {
-                       fSerialPort = serialPort;
-                       setOutputStream(serialPort.getOutputStream());
-                       setInputStream(serialPort.getInputStream());
-               }
-       }
-       protected CommPortIdentifier getSerialPortIdentifier() {
-               return fSerialPortIdentifier;
-       }
-       protected void setSerialPortIdentifier(CommPortIdentifier serialPortIdentifier) {
-               //System.out.println("setSerialPortId: "+Thread.currentThread().getName()+ " - "+serialPortIdentifier + " - "+System.currentTimeMillis());
-               fSerialPortIdentifier = serialPortIdentifier;
-       }
-       void setSerialPortHandler(SerialPortHandler serialPortHandler) {
-               fTerminalSerialPortHandler=serialPortHandler;
-       }
-       SerialPortHandler getSerialPortHandler() {
-               return fTerminalSerialPortHandler;
-       }
-       /**
-        * Return the Serial Settings.
-        *
-        * @return the settings for a concrete connection.
-        */
-       public ISerialSettings getSerialSettings() {
-               return fSettings;
-       }
-       @Override
-       public void setDefaultSettings() {
-           fSettings.load(new NullSettingsStore());
-       }
-       @Override
+        // TODO
+    }
+
+    protected SerialPort getSerialPort() {
+        return fSerialPort;
+    }
+
+    /**
+     * sets the socket to null
+     */
+    void cleanSerialPort() {
+        fSerialPort = null;
+        setInputStream(null);
+        setOutputStream(null);
+    }
+
+    protected void setSerialPort(SerialPort serialPort) throws IOException {
+        cleanSerialPort();
+        if (serialPort != null) {
+            fSerialPort = serialPort;
+            setOutputStream(serialPort.getOutputStream());
+            setInputStream(serialPort.getInputStream());
+        }
+    }
+
+    protected CommPortIdentifier getSerialPortIdentifier() {
+        return fSerialPortIdentifier;
+    }
+
+    protected void setSerialPortIdentifier(CommPortIdentifier serialPortIdentifier) {
+        // System.out.println("setSerialPortId: "+Thread.currentThread().getName()+ " - "+serialPortIdentifier + " - "+System.currentTimeMillis());
+        fSerialPortIdentifier = serialPortIdentifier;
+    }
+
+    void setSerialPortHandler(SerialPortHandler serialPortHandler) {
+        fTerminalSerialPortHandler = serialPortHandler;
+    }
+
+    SerialPortHandler getSerialPortHandler() {
+        return fTerminalSerialPortHandler;
+    }
+
+    /**
+     * Return the Serial Settings.
+     * @return the settings for a concrete connection.
+     */
+    public ISerialSettings getSerialSettings() {
+        return fSettings;
+    }
+
+    @Override
+    public void setDefaultSettings() {
+        fSettings.load(new NullSettingsStore());
+    }
+
+    @Override
     public String getSettingsSummary() {
-               return fSettings.getSummary();
-       }
-       @Override
+        return fSettings.getSummary();
+    }
+
+    @Override
     public void load(ISettingsStore store) {
-               fSettings.load(store);
-       }
-       @Override
+        fSettings.load(store);
+    }
+
+    @Override
     public void save(ISettingsStore store) {
-               fSettings.save(store);
-       }
-
-       /* Tizen */
-       public void setCaptureStream(OutputStream captureStream) {
-               fTerminalSerialPortHandler.setCaptureStream(captureStream);
-       }
-       /* ===== */
+        fSettings.save(store);
+    }
+
+    /* Tizen */
+    @Override
+    public void setCaptureStream(OutputStream captureStream) {
+        fTerminalSerialPortHandler.setCaptureStream(captureStream);
+    }
+    /* ===== */
 }
index 45913e2..a1b3d37 100644 (file)
@@ -37,102 +37,104 @@ import gnu.io.SerialPortEventListener;
 public class SerialPortHandler implements SerialPortEventListener, CommPortOwnershipListener {
 
     /* default */ final ITerminalControl fControl;
-       /* default */ final SerialConnector fConn;
-       protected byte[] bytes = new byte[2048];
-       /* Tizen */
-       // for saveLog function
-       private OutputStream captureStream = null;
-       /* ===== */
-
-       /**
-        * UNDER CONSTRUCTION
-        * @param control TODO
-        */
-       public SerialPortHandler(SerialConnector conn,ITerminalControl control) {
-               super();
-               fControl = control;
-               fConn=conn;
-       }
-
-       // Message handlers
-
-       /**
-        * UNDER CONSTRUCTION
-        */
-       public void onSerialDataAvailable(Object data) {
-               try {
-                       while (fConn.getInputStream() != null && fConn.getInputStream().available() > 0) {
-                               int nBytes = fConn.getInputStream().read(bytes);
-                               /* Tizen */
-
-                               // original
-                               // fControl.getRemoteToTerminalOutputStream().write(bytes, 0, nBytes);
-                               // original end
-
-                               if(nBytes > 0) {
-                                       fControl.getRemoteToTerminalOutputStream().write(bytes, 0, nBytes);
-                                       if(captureStream != null) {
-                                               captureStream.write(bytes, 0, nBytes);
-                                       }
-                               }
-                               /* ===== */
-                       }
-               } catch (IOException ex) {
-                       fControl.displayTextInTerminal(ex.getMessage());
-               } catch (Exception exception) {
-                       Logger.logException(exception);
-               }
-       }
-
-       public void onSerialOwnershipRequested(Object data) {
-               //Bug 221184: We immediately release the port on any ownership request
-               try {
-                       throw new Exception();
-               } catch (Exception e) {
-                       StackTraceElement[] elems = e.getStackTrace();
-                       final String requester = elems[elems.length - 4].getClassName();
-                       Display.getDefault().asyncExec(new Runnable() {
-                               @Override
+    /* default */ final SerialConnector fConn;
+    protected byte[] bytes = new byte[2048];
+    /* Tizen */
+    // for saveLog function
+    private OutputStream captureStream = null;
+    /* ===== */
+
+    /**
+     * UNDER CONSTRUCTION
+     * @param control TODO
+     */
+    public SerialPortHandler(SerialConnector conn, ITerminalControl control) {
+        super();
+        fControl = control;
+        fConn = conn;
+    }
+
+    // Message handlers
+
+    /**
+     * UNDER CONSTRUCTION
+     */
+    public void onSerialDataAvailable(Object data) {
+        try {
+            while (fConn.getInputStream() != null && fConn.getInputStream().available() > 0) {
+                int nBytes = fConn.getInputStream().read(bytes);
+                /* Tizen */
+
+                // original
+                // fControl.getRemoteToTerminalOutputStream().write(bytes, 0, nBytes);
+                // original end
+
+                if (nBytes > 0) {
+                    fControl.getRemoteToTerminalOutputStream().write(bytes, 0, nBytes);
+                    if (captureStream != null) {
+                        captureStream.write(bytes, 0, nBytes);
+                    }
+                }
+                /* ===== */
+            }
+        } catch (IOException ex) {
+            fControl.displayTextInTerminal(ex.getMessage());
+        } catch (Exception exception) {
+            Logger.logException(exception);
+        }
+    }
+
+    public void onSerialOwnershipRequested(Object data) {
+        // Bug 221184: We immediately release the port on any ownership request
+        try {
+            throw new Exception();
+        } catch (Exception e) {
+            StackTraceElement[] elems = e.getStackTrace();
+            final String requester = elems[elems.length - 4].getClassName();
+            Display.getDefault().asyncExec(new Runnable() {
+                @Override
                 public void run() {
-                                       fConn.disconnect();
-                                       String req = requester;
-                                       String myPackage = this.getClass().getPackage().getName();
-                                       if (req.startsWith(myPackage)) {
-                                               req = Messages.SerialConnectWorker_ANOTHER_TERMINAL;
-                                       }
-                                       fControl.displayTextInTerminal(NLS.bind(Messages.SerialConnectWorker_OWNERSHIP_GRANTED, req));
-                               }
-                       });
-                       fConn.disconnect();
-               }
-       }
-
-       // SerialPortEventListener interface
-       @Override
+                    fConn.disconnect();
+                    String req = requester;
+                    String myPackage = this.getClass().getPackage().getName();
+                    if (req.startsWith(myPackage)) {
+                        req = Messages.SerialConnectWorker_ANOTHER_TERMINAL;
+                    }
+                    fControl.displayTextInTerminal(NLS.bind(Messages.SerialConnectWorker_OWNERSHIP_GRANTED, req));
+                }
+            });
+            fConn.disconnect();
+        }
+    }
+
+    // SerialPortEventListener interface
+    @Override
     public void serialEvent(SerialPortEvent event) {
-               switch (event.getEventType()) {
-               case SerialPortEvent.DATA_AVAILABLE:
-                       onSerialDataAvailable(null);
-                       break;
-               }
-       }
-
-       // CommPortOwnershipListener interface
-
-       /**
-        * UNDER CONSTRUCTION
-        */
-       @Override
+        switch (event.getEventType()) {
+        case SerialPortEvent.DATA_AVAILABLE:
+            onSerialDataAvailable(null);
+            break;
+        }
+    }
+
+    // CommPortOwnershipListener interface
+
+    /**
+     * UNDER CONSTRUCTION
+     */
+    @Override
     public void ownershipChange(int nType) {
-               switch (nType) {
-               case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
-                       onSerialOwnershipRequested(null);
-                       break;
-               }
-       }
-       /* Tizen */
-       public void setCaptureStream(OutputStream captureStream) {
-               this.captureStream = captureStream;
-       }
-       /* ===== */
-}
\ No newline at end of file
+        switch (nType) {
+        case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
+            onSerialOwnershipRequested(null);
+            break;
+        }
+    }
+
+    /* Tizen */
+    public void setCaptureStream(OutputStream captureStream) {
+        this.captureStream = captureStream;
+
+    }
+    /* ===== */
+}
index cfbdabe..7d405f1 100644 (file)
@@ -8,11 +8,12 @@
  * Contributors:
  * Michael Scharf (Wind River) - initial API and implementation
  * Michael Scharf (Wind River) - [200541] Extract from TerminalConnectorExtension.TerminalConnectorProxy
- * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl 
+ * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl
  * Uwe Stieber (Wind River) - [282996] [terminal][api] Add "hidden" attribute to terminal connector extension point
  *******************************************************************************/
 package org.eclipse.tm.internal.terminal.connector;
 
+import java.io.FileOutputStream;
 import java.io.OutputStream;
 
 import org.eclipse.core.runtime.IAdaptable;
@@ -27,197 +28,205 @@ import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
 import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
 
 /**
- * An {@link ITerminalConnector} instance, also known as terminal connection
- * type, for maintaining a single terminal connection.
- *
- * It provides all terminal connector functions that can be provided by static
- * markup without loading the actual implementation class. The actual
- * {@link TerminalConnectorImpl} implementation class is lazily loaded by the
- * provided {@link TerminalConnector.Factory} interface when needed. class, and
- * delegates to the actual implementation when needed. The following methods can
- * be called without initializing the contributed implementation class:
- * {@link #getId()}, {@link #getName()}, {@link #getSettingsSummary()},{@link #load(ISettings)},
- * {@link #setTerminalSize(int, int)}, {@link #save(ISettings)},
- * {@link #getAdapter(Class)}
- *
+ * An {@link ITerminalConnector} instance, also known as terminal connection type, for maintaining a single terminal connection. It provides all terminal connector functions that can be provided by
+ * static markup without loading the actual implementation class. The actual {@link TerminalConnectorImpl} implementation class is lazily loaded by the provided {@link TerminalConnector.Factory}
+ * interface when needed. class, and delegates to the actual implementation when needed. The following methods can be called without initializing the contributed implementation class: {@link #getId()}
+ * , {@link #getName()}, {@link #getSettingsSummary()},{@link #load(ISettings)}, {@link #setTerminalSize(int, int)}, {@link #save(ISettings)}, {@link #getAdapter(Class)}
  * @noextend This class is not intended to be subclassed by clients.
- * @noinstantiate This class is not intended to be instantiated by clients.
- *                Clients can get terminal connector instances through the
- *                {@link TerminalConnectorExtension} class.
+ * @noinstantiate This class is not intended to be instantiated by clients. Clients can get terminal connector instances through the {@link TerminalConnectorExtension} class.
  * @since org.eclipse.tm.terminal 2.0
  */
 public class TerminalConnector implements ITerminalConnector {
-       /**
-        * Creates an instance of TerminalConnectorImpl. This is used to lazily load
-        * classed defined in extensions.
-        *
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       public interface Factory {
-               /**
-                * Factory method to create the actual terminal connector implementation
-                * when needed.
-                *
-                * @return a Connector
-                * @throws Exception
-                */
-               TerminalConnectorImpl makeConnector() throws Exception;
-       }
-       /**
-        * The factory for creating impl instances.
-        */
-       private final TerminalConnector.Factory fTerminalConnectorFactory;
-       /**
-        * The (display) name of the TerminalConnector
-        */
-       private final String fName;
-       /**
-        * The unique id the connector
-        */
-       private final String fId;
-       /**
-        * Flag to mark the connector as hidden.
-        */
-       private final boolean fHidden;
-       /**
-        * The connector
-        */
-       private TerminalConnectorImpl fConnector;
-       /**
-        * If the initialization of the class specified in the extension fails,
-        * this variable contains the error
-        */
-       private Exception fException;
-       /**
-        * The store might be set before the real connector is initialized.
-        * This keeps the value until the connector is created.
-        */
-       private ISettingsStore fStore;
-       /**
-        * Constructor for the terminal connector.
-        *
-        * @param terminalConnectorFactory Factory for lazily instantiating the
-        *            TerminalConnectorImpl when needed.
-        * @param id terminal connector ID. The connector is publicly known under
-        *            this ID.
-        * @param name translatable name to display the connector in the UI.
-        */
-       public TerminalConnector(TerminalConnector.Factory terminalConnectorFactory, String id, String name, boolean hidden) {
-               fTerminalConnectorFactory = terminalConnectorFactory;
-               fId = id;
-               fName = name;
-               fHidden = hidden;
-       }
-       public String getInitializationErrorMessage() {
-               getConnectorImpl();
-               if(fException!=null)
-                       return fException.getLocalizedMessage();
-               return null;
-       }
-       public String getId() {
-               return fId;
-       }
-       public String getName() {
-               return fName;
-       }
-       public boolean isHidden() {
-               return fHidden;
-       }
-       private TerminalConnectorImpl getConnectorImpl() {
-               if(!isInitialized()) {
-                       try {
-                               fConnector=fTerminalConnectorFactory.makeConnector();
-                               fConnector.initialize();
-                       } catch (Exception e) {
-                               fException=e;
-                               fConnector=new TerminalConnectorImpl(){
-                                       public void connect(ITerminalControl control) {
-                                               // super.connect(control);
-                                               control.setState(TerminalState.CLOSED);
-                                               control.setMsg(getInitializationErrorMessage());
-                                       }
-                                       public OutputStream getTerminalToRemoteStream() {
-                                               return null;
-                                       }
-                                       public String getSettingsSummary() {
-                                               return null;
-                                       }};
-                               // that's the place where we log the exception
-                               Logger.logException(e);
-                       }
-                       if(fConnector!=null && fStore!=null)
-                               fConnector.load(fStore);
-               }
-               return fConnector;
-       }
-
-       public boolean isInitialized() {
-               return fConnector!=null || fException!=null;
-       }
-       public void connect(ITerminalControl control) {
-               getConnectorImpl().connect(control);
-       }
-       public void disconnect() {
-               getConnectorImpl().disconnect();
-       }
-       public OutputStream getTerminalToRemoteStream() {
-               return getConnectorImpl().getTerminalToRemoteStream();
-       }
-       public String getSettingsSummary() {
-               if(fConnector!=null)
-                       return getConnectorImpl().getSettingsSummary();
-               else
-                       return TerminalMessages.NotInitialized;
-       }
-       public boolean isLocalEcho() {
-               return getConnectorImpl().isLocalEcho();
-       }
-       public void load(ISettingsStore store) {
-               if(fConnector==null) {
-                       fStore=store;
-               } else {
-                       getConnectorImpl().load(store);
-               }
-       }
-       @Override
-       public void setDefaultSettings() {
-               getConnectorImpl().setDefaultSettings();
-       }
-       public void save(ISettingsStore store) {
-               // no need to save the settings: it cannot have changed
-               // because we are not initialized....
-               if(fConnector!=null)
-                       getConnectorImpl().save(store);
-       }
-       public void setTerminalSize(int newWidth, int newHeight) {
-               // we assume that setTerminalSize is called also after
-               // the terminal has been initialized. Else we would have to cache
-               // the values....
-               if(fConnector!=null) {
-                       fConnector.setTerminalSize(newWidth, newHeight);
-               }
-       }
-       public Object getAdapter(Class adapter) {
-               TerminalConnectorImpl connector=null;
-               if(isInitialized())
-                       connector=getConnectorImpl();
-               // if we cannot create the connector then we cannot adapt...
-               if(connector!=null) {
-                       // maybe the connector is adaptable
-                       if(connector instanceof IAdaptable) {
-                               Object result =((IAdaptable)connector).getAdapter(adapter);
-                               // Not sure if the next block is needed....
-                               if(result==null)
-                                       //defer to the platform
-                                       result= Platform.getAdapterManager().getAdapter(connector, adapter);
-                               if(result!=null)
-                                       return result;
-                       }
-                       // maybe the real adapter is what we need....
-                       if(adapter.isInstance(connector))
-                               return connector;
-               }
-               // maybe we have to be adapted....
-               return Platform.getAdapterManager().getAdapter(this, adapter);
-       }
-}
\ No newline at end of file
+    /**
+     * Creates an instance of TerminalConnectorImpl. This is used to lazily load classed defined in extensions.
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    public interface Factory {
+        /**
+         * Factory method to create the actual terminal connector implementation when needed.
+         * @return a Connector
+         * @throws Exception
+         */
+        TerminalConnectorImpl makeConnector() throws Exception;
+    }
+
+    /**
+     * The factory for creating impl instances.
+     */
+    private final TerminalConnector.Factory fTerminalConnectorFactory;
+    /**
+     * The (display) name of the TerminalConnector
+     */
+    private final String fName;
+    /**
+     * The unique id the connector
+     */
+    private final String fId;
+    /**
+     * Flag to mark the connector as hidden.
+     */
+    private final boolean fHidden;
+    /**
+     * The connector
+     */
+    private TerminalConnectorImpl fConnector;
+    /**
+     * If the initialization of the class specified in the extension fails, this variable contains the error
+     */
+    private Exception fException;
+    /**
+     * The store might be set before the real connector is initialized. This keeps the value until the connector is created.
+     */
+    private ISettingsStore fStore;
+
+    /**
+     * Constructor for the terminal connector.
+     * @param terminalConnectorFactory Factory for lazily instantiating the TerminalConnectorImpl when needed.
+     * @param id terminal connector ID. The connector is publicly known under this ID.
+     * @param name translatable name to display the connector in the UI.
+     */
+    public TerminalConnector(TerminalConnector.Factory terminalConnectorFactory, String id, String name, boolean hidden) {
+        fTerminalConnectorFactory = terminalConnectorFactory;
+        fId = id;
+        fName = name;
+        fHidden = hidden;
+    }
+
+    public String getInitializationErrorMessage() {
+        getConnectorImpl();
+        if (fException != null)
+            return fException.getLocalizedMessage();
+        return null;
+    }
+
+    public String getId() {
+        return fId;
+    }
+
+    public String getName() {
+        return fName;
+    }
+
+    public boolean isHidden() {
+        return fHidden;
+    }
+
+    private TerminalConnectorImpl getConnectorImpl() {
+        if (!isInitialized()) {
+            try {
+                fConnector = fTerminalConnectorFactory.makeConnector();
+                fConnector.initialize();
+            } catch (Exception e) {
+                fException = e;
+                fConnector = new TerminalConnectorImpl() {
+                    public void connect(ITerminalControl control) {
+                        // super.connect(control);
+                        control.setState(TerminalState.CLOSED);
+                        control.setMsg(getInitializationErrorMessage());
+                    }
+
+                    public OutputStream getTerminalToRemoteStream() {
+                        return null;
+                    }
+
+                    public String getSettingsSummary() {
+                        return null;
+                    }
+                };
+                // that's the place where we log the exception
+                Logger.logException(e);
+            }
+            if (fConnector != null && fStore != null)
+                fConnector.load(fStore);
+        }
+        return fConnector;
+    }
+
+    public boolean isInitialized() {
+        return fConnector != null || fException != null;
+    }
+
+    public void connect(ITerminalControl control) {
+        getConnectorImpl().connect(control);
+    }
+
+    public void disconnect() {
+        getConnectorImpl().disconnect();
+    }
+
+    public OutputStream getTerminalToRemoteStream() {
+        return getConnectorImpl().getTerminalToRemoteStream();
+    }
+
+    public String getSettingsSummary() {
+        if (fConnector != null)
+            return getConnectorImpl().getSettingsSummary();
+        else
+            return TerminalMessages.NotInitialized;
+    }
+
+    public boolean isLocalEcho() {
+        return getConnectorImpl().isLocalEcho();
+    }
+
+    public void load(ISettingsStore store) {
+        if (fConnector == null) {
+            fStore = store;
+        } else {
+            getConnectorImpl().load(store);
+        }
+    }
+
+    @Override
+    public void setDefaultSettings() {
+        getConnectorImpl().setDefaultSettings();
+    }
+
+    public void save(ISettingsStore store) {
+        // no need to save the settings: it cannot have changed
+        // because we are not initialized....
+        if (fConnector != null)
+            getConnectorImpl().save(store);
+    }
+
+    public void setTerminalSize(int newWidth, int newHeight) {
+        // we assume that setTerminalSize is called also after
+        // the terminal has been initialized. Else we would have to cache
+        // the values....
+        if (fConnector != null) {
+            fConnector.setTerminalSize(newWidth, newHeight);
+        }
+    }
+
+    public Object getAdapter(Class adapter) {
+        TerminalConnectorImpl connector = null;
+        if (isInitialized())
+            connector = getConnectorImpl();
+        // if we cannot create the connector then we cannot adapt...
+        if (connector != null) {
+            // maybe the connector is adaptable
+            if (connector instanceof IAdaptable) {
+                Object result = ((IAdaptable) connector).getAdapter(adapter);
+                // Not sure if the next block is needed....
+                if (result == null)
+                    // defer to the platform
+                    result = Platform.getAdapterManager().getAdapter(connector, adapter);
+                if (result != null)
+                    return result;
+            }
+            // maybe the real adapter is what we need....
+            if (adapter.isInstance(connector))
+                return connector;
+        }
+        // maybe we have to be adapted....
+        return Platform.getAdapterManager().getAdapter(this, adapter);
+    }
+
+    /**
+     * Set the FileOutputStream value if null close outputStream(=stop capturing).
+     */
+    @Override
+    public void setCaptureStream(FileOutputStream fOutputStream) {
+        getConnectorImpl().setCaptureStream(fOutputStream);
+    }
+}
index 904897c..0a4d5e8 100644 (file)
@@ -14,6 +14,7 @@
  ******************************************************************************/
 package org.eclipse.tm.internal.terminal.control;
 
+import java.io.FileOutputStream;
 import java.io.UnsupportedEncodingException;
 
 import org.eclipse.swt.dnd.Clipboard;
@@ -25,77 +26,96 @@ import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
 
 /**
  * @author Michael Scharf
- *
  * @noextend This interface is not intended to be extended by clients.
  * @noimplement This interface is not intended to be implemented by clients.
  */
 public interface ITerminalViewControl {
-       /**
-        * Set the encoding that the Terminal uses to decode byte streams into
-        * characters.
-        *
-        * @see ITerminalControl#setEncoding(String)
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       void setEncoding(String encoding) throws UnsupportedEncodingException;
-
-       /**
-        * Get the Terminal's current encoding.
-        *
-        * @return the current Encoding of the Terminal.
-        * @see ITerminalControl#getEncoding()
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       String getEncoding();
+    /**
+     * Set the encoding that the Terminal uses to decode byte streams into characters.
+     * @see ITerminalControl#setEncoding(String)
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    void setEncoding(String encoding) throws UnsupportedEncodingException;
+
+    /**
+     * Get the Terminal's current encoding.
+     * @return the current Encoding of the Terminal.
+     * @see ITerminalControl#getEncoding()
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    String getEncoding();
 
     boolean isEmpty();
+
     /**
      * Sets the Terminal font
      * @deprecated use {@link #setFont(String)} in order to support bold and italic variants of the given font
      * @param font
      */
-       void setFont(Font font);
-       /**
-        * Sets the font for the Terminal, using a JFace symbolic font name, such
-        * that bold and italic variants can be leveraged.
-        * @since 3.2
-        * @param fontName
-        */
-       void setFont(String fontName);
-       void setInvertedColors(boolean invert);
-       Font getFont();
-       /**
-        * @return the text control
-        */
-       Control getControl();
-       /**
-        * @return the root of all controls
-        */
-       Control getRootControl();
+    void setFont(Font font);
+
+    /**
+     * Sets the font for the Terminal, using a JFace symbolic font name, such that bold and italic variants can be leveraged.
+     * @since 3.2
+     * @param fontName
+     */
+    void setFont(String fontName);
+
+    void setInvertedColors(boolean invert);
+
+    Font getFont();
+
+    /**
+     * @return the text control
+     */
+    Control getControl();
+
+    /**
+     * @return the root of all controls
+     */
+    Control getRootControl();
+
     boolean isDisposed();
+
     void selectAll();
+
     void clearTerminal();
+
     void copy();
+
     void paste();
+
     String getSelection();
+
     TerminalState getState();
+
     Clipboard getClipboard();
+
     void disconnectTerminal();
+
     void disposeTerminal();
+
     String getSettingsSummary();
+
     ITerminalConnector[] getConnectors();
+
     void setFocus();
+
     ITerminalConnector getTerminalConnector();
+
     void setConnector(ITerminalConnector connector);
+
     void connectTerminal();
+
     /**
      * @param write a single character to terminal
      */
     void sendKey(char arg0);
-       /**
-        * @param string write string to terminal
-        */
-       public boolean pasteString(String string);
+
+    /**
+     * @param string write string to terminal
+     */
+    public boolean pasteString(String string);
 
     boolean isConnected();
 
@@ -103,31 +123,38 @@ public interface ITerminalViewControl {
      * @param inputField null means no input field is shown
      */
     void setCommandInputField(ICommandInputField inputField);
+
+    /**
+     * @param logOutputStream null means no log is captured.
+     */
+    void setLogOutputStream(FileOutputStream fOutputStream);
+
     /**
      * @return null or the current input field
      */
     ICommandInputField getCommandInputField();
 
-       /**
-        * @return the maximum number of lines to display
-        * in the terminal view. -1 means unlimited.
-        */
-       public int getBufferLineLimit();
-
-       /**
-        * @param bufferLineLimit the maximum number of lines to show
-        * in the terminal view. -1 means unlimited.
-        */
-       public void setBufferLineLimit(int bufferLineLimit);
-       boolean isScrollLock();
-       void setScrollLock(boolean on);
-       
-       /**
-        * @since 4.1
-        */
-       void addMouseListener(ITerminalMouseListener listener);
-       /**
-        * @since 4.1
-        */
-       void removeMouseListener(ITerminalMouseListener listener);
+    /**
+     * @return the maximum number of lines to display in the terminal view. -1 means unlimited.
+     */
+    public int getBufferLineLimit();
+
+    /**
+     * @param bufferLineLimit the maximum number of lines to show in the terminal view. -1 means unlimited.
+     */
+    public void setBufferLineLimit(int bufferLineLimit);
+
+    boolean isScrollLock();
+
+    void setScrollLock(boolean on);
+
+    /**
+     * @since 4.1
+     */
+    void addMouseListener(ITerminalMouseListener listener);
+
+    /**
+     * @since 4.1
+     */
+    void removeMouseListener(ITerminalMouseListener listener);
 }
diff --git a/rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/control/SaveLogOutputStream.java b/rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/control/SaveLogOutputStream.java
new file mode 100644 (file)
index 0000000..d07908c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SaveLogOutputStream
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JaeMin Kim <jm.jemin.kim@samsung.com>
+ * HyeongSeok Heo <harry.heo@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ */
+package org.eclipse.tm.internal.terminal.control;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class SaveLogOutputStream extends FileOutputStream {
+    private final File path;
+
+    public SaveLogOutputStream(File file, boolean isAppend) throws FileNotFoundException {
+        super(file, isAppend);
+        this.path = file;
+    }
+
+    public void dispose() {
+        try {
+            this.close();
+        } catch (IOException e) {
+            // ignored on purpose;
+        }
+    }
+
+    public File getPath() {
+        return path;
+    }
+}
index b5d62b5..c5514c8 100644 (file)
@@ -43,6 +43,7 @@
  *******************************************************************************/
 package org.eclipse.tm.internal.terminal.emulator;
 
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
@@ -115,1300 +116,1321 @@ import org.eclipse.ui.handlers.IHandlerService;
 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).
- *
+ * 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
-{
+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.
+     * 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 TerminalFocusListener     fFocusListener;
-    private ITerminalConnector           fConnector;
-    private final ITerminalConnector[]      fConnectors;
-       private final boolean fUseCommonPrefs;
-       private boolean connectOnEnterIfClosed  = true;
+    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 TerminalFocusListener fFocusListener;
+    private ITerminalConnector fConnector;
+    private final ITerminalConnector[] fConnectors;
+    private final boolean fUseCommonPrefs;
+    private boolean connectOnEnterIfClosed = true;
 
     PipedInputStream fInputStream;
-       private static final String defaultEncoding = Charset.defaultCharset().name();
-       private String fEncoding = defaultEncoding;
-       private InputStreamReader fInputStreamReader;
+    private static final String defaultEncoding = Charset.defaultCharset().name();
+    private String fEncoding = defaultEncoding;
+    private InputStreamReader fInputStreamReader;
+
+    private ICommandInputField fCommandInputField;
 
-       private ICommandInputField fCommandInputField;
+    private FileOutputStream fOutputStream;
 
-       private volatile TerminalState fState;
+    private volatile TerminalState fState;
 
-       private final ITerminalTextData fTerminalModel;
+    private final ITerminalTextData fTerminalModel;
 
-       private final EditActionAccelerators editActionAccelerators = new EditActionAccelerators();
+    private final EditActionAccelerators editActionAccelerators = new EditActionAccelerators();
 
-       private boolean fApplicationCursorKeys;
+    private boolean fApplicationCursorKeys;
 
-       /**
-        * Listens to changes in the preferences
-        */
-       private final IPropertyChangeListener fPreferenceListener=new IPropertyChangeListener() {
-               @Override
+    /**
+     * Listens to changes in the preferences
+     */
+    private final IPropertyChangeListener fPreferenceListener = new IPropertyChangeListener() {
+        @Override
         public void propertyChange(PropertyChangeEvent event) {
-                       if(event.getProperty().equals(ITerminalConstants.PREF_BUFFERLINES)
-                                       || event.getProperty().equals(ITerminalConstants.PREF_INVERT_COLORS)) {
-                               updatePreferences();
-                       }
-               }
-       };
-       private final IPropertyChangeListener fFontListener = new IPropertyChangeListener() {
-               @Override
+            if (event.getProperty().equals(ITerminalConstants.PREF_BUFFERLINES)
+                    || event.getProperty().equals(ITerminalConstants.PREF_INVERT_COLORS)) {
+                updatePreferences();
+            }
+        }
+    };
+    private final IPropertyChangeListener fFontListener = new IPropertyChangeListener() {
+        @Override
         public void propertyChange(PropertyChangeEvent event) {
-                       if (event.getProperty().equals(ITerminalConstants.FONT_DEFINITION)) {
-                               onTerminalFontChanged();
-                       }
-               }
-       };
-
-       /**
-        * Is protected by synchronize on this
-        */
-       volatile private Job fJob;
-
-       private PollingTextCanvasModel fPollingTextCanvasModel;
-
-       public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
-               this(target, wndParent, connectors, false);
-       }
-
-       /**
-        * Instantiate a Terminal widget.
-        * @param target Callback for notifying the owner of Terminal state changes.
-        * @param wndParent The Window parent to embed the Terminal in.
-        * @param connectors Provided connectors.
-        * @param useCommonPrefs If <code>true</code>, the Terminal widget will pick up settings
-        *    from the <code>org.eclipse.tm.terminal.TerminalPreferencePage</code> Preference page.
-        *    Otherwise, clients need to maintain settings themselves.
-        * @since 3.2
-        */
-       public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors, boolean useCommonPrefs) {
-               fConnectors=connectors;
-               fUseCommonPrefs = useCommonPrefs;
-               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
+            if (event.getProperty().equals(ITerminalConstants.FONT_DEFINITION)) {
+                onTerminalFontChanged();
+            }
+        }
+    };
+
+    /**
+     * Is protected by synchronize on this
+     */
+    volatile private Job fJob;
+
+    private PollingTextCanvasModel fPollingTextCanvasModel;
+
+    public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors) {
+        this(target, wndParent, connectors, false);
+    }
+
+    /**
+     * Instantiate a Terminal widget.
+     * @param target Callback for notifying the owner of Terminal state changes.
+     * @param wndParent The Window parent to embed the Terminal in.
+     * @param connectors Provided connectors.
+     * @param useCommonPrefs If <code>true</code>, the Terminal widget will pick up settings from the <code>org.eclipse.tm.terminal.TerminalPreferencePage</code> Preference page. Otherwise, clients
+     *            need to maintain settings themselves.
+     * @since 3.2
+     */
+    public VT100TerminalControl(ITerminalListener target, Composite wndParent, ITerminalConnector[] connectors, boolean useCommonPrefs) {
+        fConnectors = connectors;
+        fUseCommonPrefs = useCommonPrefs;
+        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
+        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;
-       }
+        return fEncoding;
+    }
 
-       @Override
+    @Override
     public ITerminalConnector[] getConnectors() {
-               return fConnectors;
-       }
+        return fConnectors;
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#copy()
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#copy()
+     */
+    @Override
     public void copy() {
-               copy(DND.CLIPBOARD);
-       }
-
-       private void copy(int clipboardType) {
-               String selection = getSelection();
-               if (selection.length() > 0) {
-                       Object[] data = new Object[] { selection };
-                       Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
-                       fClipboard.setContents(data, types, clipboardType);
-               }
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#paste()
-        */
-       @Override
+        copy(DND.CLIPBOARD);
+    }
+
+    private void copy(int clipboardType) {
+        String selection = getSelection();
+        if (selection.length() > 0) {
+            Object[] data = new Object[] { selection };
+            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
+        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
+        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();
-               if (fTerminalListener instanceof ITerminalListener2) {
-                       ((ITerminalListener2)fTerminalListener).setTerminalSelectionChanged();
-               }
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#sendKey(char)
-        */
-       @Override
+        getCtlText().selectAll();
+        if (fTerminalListener instanceof ITerminalListener2) {
+            ((ITerminalListener2) fTerminalListener).setTerminalSelectionChanged();
+        }
+    }
+
+    /* (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
+        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();
-               getCtlText().clearSelection();
-               if (fTerminalListener instanceof ITerminalListener2) {
-                       ((ITerminalListener2)fTerminalListener).setTerminalSelectionChanged();
-               }
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getClipboard()
-        */
-       @Override
+        // The TerminalText object does all text manipulation.
+        getTerminalText().clearTerminal();
+        getCtlText().clearSelection();
+        if (fTerminalListener instanceof ITerminalListener2) {
+            ((ITerminalListener2) fTerminalListener).setTerminalSelectionChanged();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#getClipboard()
+     */
+    @Override
     public Clipboard getClipboard() {
-               return fClipboard;
-       }
+        return fClipboard;
+    }
 
-       /**
-        * @return non null selection
-        */
-       @Override
+    /**
+     * @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
+        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 void setFocus() {
-               getCtlText().setFocus();
-       }
+        getCtlText().setFocus();
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isEmpty()
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isEmpty()
+     */
+    @Override
     public boolean isEmpty() {
-               return getCtlText().isEmpty();
-       }
+        return getCtlText().isEmpty();
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isDisposed()
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isDisposed()
+     */
+    @Override
     public boolean isDisposed() {
-               return getCtlText().isDisposed();
-       }
+        return getCtlText().isDisposed();
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isConnected()
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isConnected()
+     */
+    @Override
     public boolean isConnected() {
-               return fState==TerminalState.CONNECTED;
-       }
+        return fState == TerminalState.CONNECTED;
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disposeTerminal()
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disposeTerminal()
+     */
+    @Override
     public void disposeTerminal() {
-               Logger.log("entered."); //$NON-NLS-1$
-               if(fUseCommonPrefs) {
-                       TerminalPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(fPreferenceListener);
-                       JFaceResources.getFontRegistry().removeListener(fFontListener);
-               }
-               disconnectTerminal();
-               fClipboard.dispose();
-               getTerminalText().dispose();
-       }
-
-       @Override
+        Logger.log("entered."); //$NON-NLS-1$
+        if (fUseCommonPrefs) {
+            TerminalPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(fPreferenceListener);
+            JFaceResources.getFontRegistry().removeListener(fFontListener);
+        }
+        disconnectTerminal();
+        fClipboard.dispose();
+        getTerminalText().dispose();
+    }
+
+    @Override
     public void connectTerminal() {
-               Logger.log("entered."); //$NON-NLS-1$
-               if(getTerminalConnector()==null)
-                       return;
-               fTerminalText.resetState();
-               fApplicationCursorKeys = false;
-               if(fConnector.getInitializationErrorMessage()!=null) {
-                       showErrorMessage(NLS.bind(
-                                       TerminalMessages.CannotConnectTo,
-                                       fConnector.getName(),
-                                       fConnector.getInitializationErrorMessage()));
-                       // we cannot connect because the connector was not initialized
-                       return;
-               }
-               // clean the error message
-               setMsg(""); //$NON-NLS-1$
-               getTerminalConnector().connect(this);
-               waitForConnect();
-       }
-
-       @Override
+        Logger.log("entered."); //$NON-NLS-1$
+        if (getTerminalConnector() == null)
+            return;
+        fTerminalText.resetState();
+        fApplicationCursorKeys = false;
+        if (fConnector.getInitializationErrorMessage() != null) {
+            showErrorMessage(NLS.bind(
+                    TerminalMessages.CannotConnectTo,
+                    fConnector.getName(),
+                    fConnector.getInitializationErrorMessage()));
+            // we cannot connect because the connector was not initialized
+            return;
+        }
+        // clean the error message
+        setMsg(""); //$NON-NLS-1$
+        getTerminalConnector().connect(this);
+        waitForConnect();
+    }
+
+    @Override
     public ITerminalConnector getTerminalConnector() {
-               return fConnector;
-       }
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disconnectTerminal()
-        */
-       @Override
+        return fConnector;
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#disconnectTerminal()
+     */
+    @Override
     public void disconnectTerminal() {
-               Logger.log("entered."); //$NON-NLS-1$
+        Logger.log("entered."); //$NON-NLS-1$
 
-               //Disconnect the remote side first
-               if (getState()!=TerminalState.CLOSED) {
-                       if(getTerminalConnector()!=null) {
-                               getTerminalConnector().disconnect();
-                       }
-               }
+        // 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.
+        // Ensure that a new Job can be started; then clean up old Job.
         Job job;
-        synchronized(this) {
+        synchronized (this) {
             job = fJob;
             fJob = null;
         }
-        if (job!=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();
+            if (t != null)
+                t.interrupt();
             try {
                 job.join();
-            } catch (InterruptedException e) {}
+            } catch (InterruptedException e) {
+            }
         }
-               fPollingTextCanvasModel.stopPolling();
-       }
-
-       private void waitForConnect() {
-               Logger.log("entered."); //$NON-NLS-1$
-
-               // TODO Eliminate the nested dispatch loop
-               do {
-                       if (!fDisplay.readAndDispatch())
-                               fDisplay.sleep();
-               } while (getState()==TerminalState.CONNECTING);
-
-               if (getCtlText().isDisposed()) {
-                       disconnectTerminal();
-                       return;
-               }
-               if (getMsg().length() > 0) {
-                       showErrorMessage(getMsg());
-                       disconnectTerminal();
-                       return;
-               }
-               if (getCtlText().isFocusControl()) {
-                       if (getState() == TerminalState.CONNECTED)
-                               fFocusListener.captureKeyEvents(true);
-               }
-               fPollingTextCanvasModel.startPolling();
-               startReaderJob();
-       }
-
-       private synchronized void startReaderJob() {
-               if(fJob==null) {
-                       fJob=new Job("Terminal data reader") { //$NON-NLS-1$
-                               @Override
+        fPollingTextCanvasModel.stopPolling();
+    }
+
+    private void waitForConnect() {
+        Logger.log("entered."); //$NON-NLS-1$
+
+        // TODO Eliminate the nested dispatch loop
+        do {
+            if (!fDisplay.readAndDispatch())
+                fDisplay.sleep();
+        } while (getState() == TerminalState.CONNECTING);
+
+        if (getCtlText().isDisposed()) {
+            disconnectTerminal();
+            return;
+        }
+        if (getMsg().length() > 0) {
+            showErrorMessage(getMsg());
+            disconnectTerminal();
+            return;
+        }
+        if (getCtlText().isFocusControl()) {
+            if (getState() == TerminalState.CONNECTED)
+                fFocusListener.captureKeyEvents(true);
+        }
+        fPollingTextCanvasModel.startPolling();
+        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) {
-               Logger.log(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
+                    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) {
+        Logger.log(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.
-
-                                       byte[] bytesToSend = String.valueOf(chKey).getBytes(fEncoding);
-                                       StringBuilder b = new StringBuilder("sending ESC"); //$NON-NLS-1$
-                                       for (int i = 0; i < bytesToSend.length; i++) {
-                                               if (i != 0) b.append(" +"); //$NON-NLS-1$
-                                               b.append(" '" + bytesToSend[i] + "'"); //$NON-NLS-1$ //$NON-NLS-2$
-                                       }
-                                       Logger.log(b.toString());
-                                       os.write('\u001b');
-                                       os.write(bytesToSend);
-                               } else {
-                                       byte[] bytesToSend = String.valueOf(chKey).getBytes(fEncoding);
-                                       StringBuilder b = new StringBuilder("sending"); //$NON-NLS-1$
-                                       for (int i = 0; i < bytesToSend.length; i++) {
-                                               if (i != 0) b.append(" +"); //$NON-NLS-1$
-                                               b.append(" '" + bytesToSend[i] + "'"); //$NON-NLS-1$ //$NON-NLS-2$
-                                       }
-                                       Logger.log(b.toString());
-                                       os.write(bytesToSend);
-                               }
-                               os.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
+        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.
+
+                    byte[] bytesToSend = String.valueOf(chKey).getBytes(fEncoding);
+                    StringBuilder b = new StringBuilder("sending ESC"); //$NON-NLS-1$
+                    for (int i = 0; i < bytesToSend.length; i++) {
+                        if (i != 0)
+                            b.append(" +"); //$NON-NLS-1$
+                        b.append(" '" + bytesToSend[i] + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+                    }
+                    Logger.log(b.toString());
+                    os.write('\u001b');
+                    os.write(bytesToSend);
+                } else {
+                    byte[] bytesToSend = String.valueOf(chKey).getBytes(fEncoding);
+                    StringBuilder b = new StringBuilder("sending"); //$NON-NLS-1$
+                    for (int i = 0; i < bytesToSend.length; i++) {
+                        if (i != 0)
+                            b.append(" +"); //$NON-NLS-1$
+                        b.append(" '" + bytesToSend[i] + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+                    }
+                    Logger.log(b.toString());
+                    os.write(bytesToSend);
+                }
+                os.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);
-               boolean wasDisposed = true;
-               TerminalState oldState = fState;
-               fState = TerminalState.CLOSED;
-               if (fClipboard != null && !fClipboard.isDisposed()) {
-                       // terminal was not disposed (DnD)
-                       wasDisposed = false;
-                       fClipboard.dispose();
-                       fPollingTextCanvasModel.stopPolling();
-               }
-               if (fWndParent != null && !fWndParent.isDisposed()) {
-                       // terminal widget gets a new parent (DnD)
-                       fWndParent.dispose();
-               }
-               setupControls(parent);
-               setCommandInputField(fCommandInputField);
-               setupListeners();
-               if (fUseCommonPrefs && wasDisposed) {
-                       updatePreferences();
-                       onTerminalFontChanged();
-                       TerminalPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPreferenceListener);
-                       JFaceResources.getFontRegistry().addListener(fFontListener);
-               }
-               setupHelp(fWndParent, TerminalPlugin.HELP_VIEW);
-
-               if (!wasDisposed) {
-                       fState = oldState;
-               }
-       }
-
-       /*
-        * (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.control.ITerminalViewControl#updatePreferences()
-        */
-       private void updatePreferences() {
-               int bufferLineLimit = Platform.getPreferencesService().getInt(TerminalPlugin.PLUGIN_ID, ITerminalConstants.PREF_BUFFERLINES, 0, null);
-               boolean invert = Platform.getPreferencesService().getBoolean(TerminalPlugin.PLUGIN_ID, ITerminalConstants.PREF_INVERT_COLORS, false, null);
-               setBufferLineLimit(bufferLineLimit);
-               setInvertedColors(invert);
-       }
-
-       private void onTerminalFontChanged() {
-               // set the font for all
-               setFont(ITerminalConstants.FONT_DEFINITION);
-       }
-
-       /*
-        * (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.control.ITerminalViewControl#setFont(java.lang.String)
-        */
-       @Override
+        Assert.isNotNull(parent);
+        boolean wasDisposed = true;
+        TerminalState oldState = fState;
+        fState = TerminalState.CLOSED;
+        if (fClipboard != null && !fClipboard.isDisposed()) {
+            // terminal was not disposed (DnD)
+            wasDisposed = false;
+            fClipboard.dispose();
+            fPollingTextCanvasModel.stopPolling();
+        }
+        if (fWndParent != null && !fWndParent.isDisposed()) {
+            // terminal widget gets a new parent (DnD)
+            fWndParent.dispose();
+        }
+        setupControls(parent);
+        setCommandInputField(fCommandInputField);
+        setupListeners();
+        if (fUseCommonPrefs && wasDisposed) {
+            updatePreferences();
+            onTerminalFontChanged();
+            TerminalPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPreferenceListener);
+            JFaceResources.getFontRegistry().addListener(fFontListener);
+        }
+        setupHelp(fWndParent, TerminalPlugin.HELP_VIEW);
+
+        if (!wasDisposed) {
+            fState = oldState;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.control.ITerminalViewControl#updatePreferences()
+     */
+    private void updatePreferences() {
+        int bufferLineLimit = Platform.getPreferencesService().getInt(TerminalPlugin.PLUGIN_ID, ITerminalConstants.PREF_BUFFERLINES, 0, null);
+        boolean invert = Platform.getPreferencesService().getBoolean(TerminalPlugin.PLUGIN_ID, ITerminalConstants.PREF_INVERT_COLORS, false, null);
+        setBufferLineLimit(bufferLineLimit);
+        setInvertedColors(invert);
+    }
+
+    private void onTerminalFontChanged() {
+        // set the font for all
+        setFont(ITerminalConstants.FONT_DEFINITION);
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.control.ITerminalViewControl#setFont(java.lang.String)
+     */
+    @Override
     public void setFont(String fontName) {
-               Font font=JFaceResources.getFont(fontName);
-               getCtlText().setFont(font);
-               if(fCommandInputField!=null) {
-                       fCommandInputField.setFont(font);
-               }
-               // Tell the TerminalControl singleton that the font has changed.
-               fCtlText.updateFont(fontName);
-               getTerminalText().fontChanged();
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.control.ITerminalViewControl#setFont(org.eclipse.swt.graphics.Font)
-        */
-       @Override
+        Font font = JFaceResources.getFont(fontName);
+        getCtlText().setFont(font);
+        if (fCommandInputField != null) {
+            fCommandInputField.setFont(font);
+        }
+        // Tell the TerminalControl singleton that the font has changed.
+        fCtlText.updateFont(fontName);
+        getTerminalText().fontChanged();
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.control.ITerminalViewControl#setFont(org.eclipse.swt.graphics.Font)
+     */
+    @Override
     @Deprecated
-       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 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
+        return getCtlText().getFont();
+    }
+
+    @Override
     public Control getControl() {
-               return fCtlText;
-       }
-       @Override
+        return fCtlText;
+    }
+
+    @Override
     public Control getRootControl() {
-               return fWndParent;
-       }
-       protected void setupControls(Composite parent) {
-               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);
-               fPollingTextCanvasModel=new PollingTextCanvasModel(snapshot);
-               fCtlText=new TextCanvas(fWndParent,fPollingTextCanvasModel,SWT.NONE,new TextLineRenderer(fCtlText,fPollingTextCanvasModel));
-
-               fCtlText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               fCtlText.addResizeHandler(new TextCanvas.ResizeListener() {
-                       @Override
+        return fWndParent;
+    }
+
+    protected void setupControls(Composite parent) {
+        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);
+        fPollingTextCanvasModel = new PollingTextCanvasModel(snapshot);
+        fCtlText = new TextCanvas(fWndParent, fPollingTextCanvasModel, SWT.NONE, new TextLineRenderer(fCtlText, fPollingTextCanvasModel));
+
+        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
+                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);
-       }
-
-       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
+                // 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);
+    }
+
+    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
+        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);
-       }
-
-       @Override
+        if (Logger.isLogEnabled()) {
+            return new LoggingOutputStream(fInputStream.getOutputStream());
+        } else {
+            return fInputStream.getOutputStream();
+        }
+    }
+
+    protected boolean isLogCharEnabled() {
+        return TerminalPlugin.isOptionEnabled(Logger.TRACE_DEBUG_LOG_CHAR);
+    }
+
+    @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
+        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 terminalContextActivation = null;
-               private IContextActivation editContextActivation = null;
-
-               protected TerminalFocusListener() {
-                       super();
-               }
-
-               @Override
+        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 terminalContextActivation = null;
+        private IContextActivation editContextActivation = null;
+
+        protected TerminalFocusListener() {
+            super();
+        }
+
+        @Override
         @SuppressWarnings("cast")
-               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.
-                       if (getState() == TerminalState.CONNECTED)
-                               captureKeyEvents(true);
-
-                       IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
-                       editContextActivation = contextService.activateContext("org.eclipse.tm.terminal.EditContext"); //$NON-NLS-1$
-               }
-
-               @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.
+            if (getState() == TerminalState.CONNECTED)
+                captureKeyEvents(true);
+
+            IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
+            editContextActivation = contextService.activateContext("org.eclipse.tm.terminal.EditContext"); //$NON-NLS-1$
+        }
+
+        @Override
         @SuppressWarnings("cast")
-               public void focusLost(FocusEvent event) {
-                       // Enable all keybindings.
-                       captureKeyEvents(false);
-
-                       // Restore the command context to its previous value.
-
-                       IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
-                       contextService.deactivateContext(editContextActivation);
-               }
-
-               @SuppressWarnings("cast")
-               protected void captureKeyEvents(boolean capture) {
-                       IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
-                       IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
-
-                       boolean enableKeyFilter = !capture;
-                       if (bindingService.isKeyFilterEnabled() != enableKeyFilter)
-                               bindingService.setKeyFilterEnabled(enableKeyFilter);
-
-                       if (capture && terminalContextActivation == null) {
-                               // 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 absolutely _all_
-                               // key-presses.
-                               terminalContextActivation = contextService.activateContext("org.eclipse.tm.terminal.TerminalContext"); //$NON-NLS-1$
-
-                       } else if (!capture && terminalContextActivation != null) {
-                               contextService.deactivateContext(terminalContextActivation);
-                               terminalContextActivation = null;
-                       }
-               }
-       }
-
-       protected class TerminalKeyHandler extends KeyAdapter {
-               @Override
+        public void focusLost(FocusEvent event) {
+            // Enable all keybindings.
+            captureKeyEvents(false);
+
+            // Restore the command context to its previous value.
+
+            IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
+            contextService.deactivateContext(editContextActivation);
+        }
+
+        @SuppressWarnings("cast")
+        protected void captureKeyEvents(boolean capture) {
+            IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
+            IContextService contextService = (IContextService) PlatformUI.getWorkbench().getAdapter(IContextService.class);
+
+            boolean enableKeyFilter = !capture;
+            if (bindingService.isKeyFilterEnabled() != enableKeyFilter)
+                bindingService.setKeyFilterEnabled(enableKeyFilter);
+
+            if (capture && terminalContextActivation == null) {
+                // 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 absolutely _all_
+                // key-presses.
+                terminalContextActivation = contextService.activateContext("org.eclipse.tm.terminal.TerminalContext"); //$NON-NLS-1$
+
+            } else if (!capture && terminalContextActivation != null) {
+                contextService.deactivateContext(terminalContextActivation);
+                terminalContextActivation = null;
+            }
+        }
+    }
+
+    protected class TerminalKeyHandler extends KeyAdapter {
+        @Override
         public void keyPressed(KeyEvent event) {
-                       //TODO next 2 lines are probably obsolete now
-                       if (getState()==TerminalState.CONNECTING)
-                               return;
-
-                       //TODO we should no longer handle copy & paste specially.
-                       //Instead, we should have Ctrl+Shift always go to local since there is no escape sequence for this.
-                       //On Mac, Command+Anything already goes always to local.
-                       //Note that this decision means that Command will NOT be Meta in Emacs on a Remote.
-                       int accelerator = SWTKeySupport.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;
-                       int modifierKeys = event.stateMask & SWT.MODIFIER_MASK;
-                       boolean ctrlKeyPressed = (event.stateMask & SWT.CTRL) != 0;
-                       boolean onlyCtrlKeyPressed = modifierKeys == SWT.CTRL;
-                       boolean macCmdKeyPressed = (event.stateMask & SWT.COMMAND) != 0;
-
-                       // 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.
-                       boolean altKeyPressed = (event.stateMask & SWT.ALT) != 0 && !ctrlKeyPressed;
-
-                       //if (!isConnected()) {
-                       if (fState==TerminalState.CLOSED) {
-                               // Pressing ENTER while not connected causes us to connect.
-                               if (character == '\r' && isConnectOnEnterIfClosed()) {
-                                       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;
-                       }
-
-                       // TODO Linux tty is usually expecting a DEL (^?) character
-                       // but this causes issues with some telnet servers and
-                       // serial connections. Workaround: stty erase ^H
-                       //if (event.keyCode == SWT.BS) {
-                       //      sendChar(SWT.DEL, altKeyPressed);
-                       //      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.
-                       // On a Mac, the Cmd key is always used for local commands.
-
-                       if (macCmdKeyPressed || (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.
-
-                               String escSeq = null;
-                               boolean anyModifierPressed = modifierKeys != 0;
-                               boolean onlyMacCmdKeyPressed = modifierKeys == SWT.COMMAND;
-
-                               switch (event.keyCode) {
-                               case 0x1000001: // Up arrow.
-                                       if (!anyModifierPressed)
-                                               escSeq = fApplicationCursorKeys ? "\u001bOA" : "\u001b[A"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       break;
-
-                               case 0x1000002: // Down arrow.
-                                       if (!anyModifierPressed)
-                                               escSeq = fApplicationCursorKeys ? "\u001bOB" : "\u001b[B"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       break;
-
-                               case 0x1000003: // Left arrow.
-                                       if (onlyCtrlKeyPressed) {
-                                               escSeq = "\u001b[1;5D"; //$NON-NLS-1$
-                                       } else if (!anyModifierPressed) {
-                                               escSeq = fApplicationCursorKeys ? "\u001bOD" : "\u001b[D"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       } else if (onlyMacCmdKeyPressed) {
-                                               // Cmd-Left is "Home" on the Mac
-                                               escSeq = fApplicationCursorKeys ? "\u001bOH" : "\u001b[H"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       }
-                                       break;
-
-                               case 0x1000004: // Right arrow.
-                                       if (onlyCtrlKeyPressed) {
-                                               escSeq = "\u001b[1;5C"; //$NON-NLS-1$
-                                       } else if (!anyModifierPressed) {
-                                               escSeq = fApplicationCursorKeys ? "\u001bOC" : "\u001b[C"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       } else if (onlyMacCmdKeyPressed) {
-                                               // Cmd-Right is "End" on the Mac
-                                               escSeq = fApplicationCursorKeys ? "\u001bOF" : "\u001b[F"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       }
-                                       break;
-
-                               case 0x1000005: // PgUp key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[5~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000006: // PgDn key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[6~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000007: // Home key.
-                                       if (!anyModifierPressed)
-                                               escSeq = fApplicationCursorKeys ? "\u001bOH" : "\u001b[H"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       break;
-
-                               case 0x1000008: // End key.
-                                       if (!anyModifierPressed)
-                                               escSeq = fApplicationCursorKeys ? "\u001bOF" : "\u001b[F"; //$NON-NLS-1$ //$NON-NLS-2$
-                                       break;
-
-                               case 0x1000009: // Insert.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[2~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x100000a: // F1 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001bOP"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x100000b: // F2 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001bOQ"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x100000c: // F3 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001bOR"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x100000d: // F4 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001bOS"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x100000e: // F5 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[15~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x100000f: // F6 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[17~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000010: // F7 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[18~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000011: // F8 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[19~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000012: // F9 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[20~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000013: // F10 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[21~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000014: // F11 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[23~"; //$NON-NLS-1$
-                                       break;
-
-                               case 0x1000015: // F12 key.
-                                       if (!anyModifierPressed)
-                                               escSeq = "\u001b[24~"; //$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;
-                               }
-
-                               if (escSeq == null) {
-                                       // Any unmapped key should be handled locally by Eclipse
-                                       event.doit = true;
-                                       processKeyBinding(event, accelerator);
-                               } else
-                                       sendString(escSeq);
-
-                               // It's ok to return here, because we never locally echo special keys.
-
-                               return;
-                       }
-
-                       Logger.log("stateMask = " + event.stateMask); //$NON-NLS-1$
-
-                       if (onlyCtrlKeyPressed) {
-                               switch (character) {
-                               case ' ':
-                                       // 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';
-                                       break;
-                               case '/':
-                                       // Ctrl+/ is undo in emacs
-                                       character = '\u001f';
-                                       break;
-                               }
-                       }
-
-                       //TODO: At this point, Ctrl+M sends the same as Ctrl+Shift+M .
-                       //This is undesired. Fixing this here might make the special Ctrl+Shift+C
-                       //handling unnecessary further up.
-                       sendChar(character, altKeyPressed);
-
-                       // 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());
-               }
-
-               /*
-                * Process given event as Eclipse key binding.
-                */
-               @SuppressWarnings("cast")
-               private void processKeyBinding(KeyEvent event, int accelerator) {
-                       IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
-                       KeyStroke keyStroke = SWTKeySupport.convertAcceleratorToKeyStroke(accelerator);
-                       Binding binding = bindingService.getPerfectMatch(KeySequence.getInstance(keyStroke));
-                       if (binding != null) {
-                               ParameterizedCommand cmd = binding.getParameterizedCommand();
-                               if (cmd != null) {
-                                       IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
-                                       Event cmdEvent = new Event();
-                                       cmdEvent.type = SWT.KeyDown;
-                                       cmdEvent.display = event.display;
-                                       cmdEvent.widget = event.widget;
-                                       cmdEvent.character = event.character;
-                                       cmdEvent.keyCode = event.keyCode;
-                                       ////Bug - KeyEvent.keyLocation was introduced in Eclipse 3.6
-                                       ////Use reflection for now to remain backward compatible down to Eclipse 3.4
-                                       //cmdEvent.keyLocation = event.keyLocation;
-                                       try {
-                                               Field f1 = event.getClass().getField("keyLocation"); //$NON-NLS-1$
-                                               Field f2 = cmdEvent.getClass().getField("keyLocation"); //$NON-NLS-1$
-                                               f2.set(cmdEvent, f1.get(event));
-                                       } catch(NoSuchFieldException nsfe) {
-                                               /* ignore, this is Eclipse 3.5 or earlier */
-                                       } catch(Throwable t) {
-                                               t.printStackTrace();
-                                       }
-                                       cmdEvent.stateMask = event.stateMask;
-                                       event.doit = false;
-                                       try {
-                                               handlerService.executeCommand(cmd, cmdEvent);
-                                       } catch (ExecutionException e) {
-                                               TerminalPlugin.getDefault().getLog().log(
-                                                               new Status(IStatus.ERROR,TerminalPlugin.PLUGIN_ID,e.getLocalizedMessage(),e));
-                                       } catch (Exception e) {
-                                               // ignore other exceptions from cmd execution
-                                       }
-                               }
-                       }
-               }
-
-       }
-
-       @Override
-    public void setTerminalTitle(String title) {
-               fTerminalListener.setTerminalTitle(title);
-       }
+            // TODO next 2 lines are probably obsolete now
+            if (getState() == TerminalState.CONNECTING)
+                return;
+
+            // TODO we should no longer handle copy & paste specially.
+            // Instead, we should have Ctrl+Shift always go to local since there is no escape sequence for this.
+            // On Mac, Command+Anything already goes always to local.
+            // Note that this decision means that Command will NOT be Meta in Emacs on a Remote.
+            int accelerator = SWTKeySupport.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;
+            int modifierKeys = event.stateMask & SWT.MODIFIER_MASK;
+            boolean ctrlKeyPressed = (event.stateMask & SWT.CTRL) != 0;
+            boolean onlyCtrlKeyPressed = modifierKeys == SWT.CTRL;
+            boolean macCmdKeyPressed = (event.stateMask & SWT.COMMAND) != 0;
+
+            // 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.
+            boolean altKeyPressed = (event.stateMask & SWT.ALT) != 0 && !ctrlKeyPressed;
+
+            // if (!isConnected()) {
+            if (fState == TerminalState.CLOSED) {
+                // Pressing ENTER while not connected causes us to connect.
+                if (character == '\r' && isConnectOnEnterIfClosed()) {
+                    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;
+            }
+
+            // TODO Linux tty is usually expecting a DEL (^?) character
+            // but this causes issues with some telnet servers and
+            // serial connections. Workaround: stty erase ^H
+            // if (event.keyCode == SWT.BS) {
+            // sendChar(SWT.DEL, altKeyPressed);
+            // 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.
+            // On a Mac, the Cmd key is always used for local commands.
+
+            if (macCmdKeyPressed || (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.
+
+                String escSeq = null;
+                boolean anyModifierPressed = modifierKeys != 0;
+                boolean onlyMacCmdKeyPressed = modifierKeys == SWT.COMMAND;
+
+                switch (event.keyCode) {
+                case 0x1000001: // Up arrow.
+                    if (!anyModifierPressed)
+                        escSeq = fApplicationCursorKeys ? "\u001bOA" : "\u001b[A"; //$NON-NLS-1$ //$NON-NLS-2$
+                    break;
+
+                case 0x1000002: // Down arrow.
+                    if (!anyModifierPressed)
+                        escSeq = fApplicationCursorKeys ? "\u001bOB" : "\u001b[B"; //$NON-NLS-1$ //$NON-NLS-2$
+                    break;
+
+                case 0x1000003: // Left arrow.
+                    if (onlyCtrlKeyPressed) {
+                        escSeq = "\u001b[1;5D"; //$NON-NLS-1$
+                    } else if (!anyModifierPressed) {
+                        escSeq = fApplicationCursorKeys ? "\u001bOD" : "\u001b[D"; //$NON-NLS-1$ //$NON-NLS-2$
+                    } else if (onlyMacCmdKeyPressed) {
+                        // Cmd-Left is "Home" on the Mac
+                        escSeq = fApplicationCursorKeys ? "\u001bOH" : "\u001b[H"; //$NON-NLS-1$ //$NON-NLS-2$
+                    }
+                    break;
+
+                case 0x1000004: // Right arrow.
+                    if (onlyCtrlKeyPressed) {
+                        escSeq = "\u001b[1;5C"; //$NON-NLS-1$
+                    } else if (!anyModifierPressed) {
+                        escSeq = fApplicationCursorKeys ? "\u001bOC" : "\u001b[C"; //$NON-NLS-1$ //$NON-NLS-2$
+                    } else if (onlyMacCmdKeyPressed) {
+                        // Cmd-Right is "End" on the Mac
+                        escSeq = fApplicationCursorKeys ? "\u001bOF" : "\u001b[F"; //$NON-NLS-1$ //$NON-NLS-2$
+                    }
+                    break;
+
+                case 0x1000005: // PgUp key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[5~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000006: // PgDn key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[6~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000007: // Home key.
+                    if (!anyModifierPressed)
+                        escSeq = fApplicationCursorKeys ? "\u001bOH" : "\u001b[H"; //$NON-NLS-1$ //$NON-NLS-2$
+                    break;
+
+                case 0x1000008: // End key.
+                    if (!anyModifierPressed)
+                        escSeq = fApplicationCursorKeys ? "\u001bOF" : "\u001b[F"; //$NON-NLS-1$ //$NON-NLS-2$
+                    break;
+
+                case 0x1000009: // Insert.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[2~"; //$NON-NLS-1$
+                    break;
+
+                case 0x100000a: // F1 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001bOP"; //$NON-NLS-1$
+                    break;
+
+                case 0x100000b: // F2 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001bOQ"; //$NON-NLS-1$
+                    break;
+
+                case 0x100000c: // F3 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001bOR"; //$NON-NLS-1$
+                    break;
+
+                case 0x100000d: // F4 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001bOS"; //$NON-NLS-1$
+                    break;
+
+                case 0x100000e: // F5 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[15~"; //$NON-NLS-1$
+                    break;
+
+                case 0x100000f: // F6 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[17~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000010: // F7 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[18~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000011: // F8 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[19~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000012: // F9 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[20~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000013: // F10 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[21~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000014: // F11 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[23~"; //$NON-NLS-1$
+                    break;
+
+                case 0x1000015: // F12 key.
+                    if (!anyModifierPressed)
+                        escSeq = "\u001b[24~"; //$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;
+                }
+
+                if (escSeq == null) {
+                    // Any unmapped key should be handled locally by Eclipse
+                    event.doit = true;
+                    processKeyBinding(event, accelerator);
+                } else
+                    sendString(escSeq);
+
+                // It's ok to return here, because we never locally echo special keys.
+
+                return;
+            }
+
+            Logger.log("stateMask = " + event.stateMask); //$NON-NLS-1$
+
+            if (onlyCtrlKeyPressed) {
+                switch (character) {
+                case ' ':
+                    // 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';
+                    break;
+                case '/':
+                    // Ctrl+/ is undo in emacs
+                    character = '\u001f';
+                    break;
+                }
+            }
+
+            // TODO: At this point, Ctrl+M sends the same as Ctrl+Shift+M .
+            // This is undesired. Fixing this here might make the special Ctrl+Shift+C
+            // handling unnecessary further up.
+            sendChar(character, altKeyPressed);
+
+            // 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());
+        }
 
+        /*
+         * Process given event as Eclipse key binding.
+         */
+        @SuppressWarnings("cast")
+        private void processKeyBinding(KeyEvent event, int accelerator) {
+            IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
+            KeyStroke keyStroke = SWTKeySupport.convertAcceleratorToKeyStroke(accelerator);
+            Binding binding = bindingService.getPerfectMatch(KeySequence.getInstance(keyStroke));
+            if (binding != null) {
+                ParameterizedCommand cmd = binding.getParameterizedCommand();
+                if (cmd != null) {
+                    IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
+                    Event cmdEvent = new Event();
+                    cmdEvent.type = SWT.KeyDown;
+                    cmdEvent.display = event.display;
+                    cmdEvent.widget = event.widget;
+                    cmdEvent.character = event.character;
+                    cmdEvent.keyCode = event.keyCode;
+                    //// Bug - KeyEvent.keyLocation was introduced in Eclipse 3.6
+                    //// Use reflection for now to remain backward compatible down to Eclipse 3.4
+                    // cmdEvent.keyLocation = event.keyLocation;
+                    try {
+                        Field f1 = event.getClass().getField("keyLocation"); //$NON-NLS-1$
+                        Field f2 = cmdEvent.getClass().getField("keyLocation"); //$NON-NLS-1$
+                        f2.set(cmdEvent, f1.get(event));
+                    } catch (NoSuchFieldException nsfe) {
+                        /* ignore, this is Eclipse 3.5 or earlier */
+                    } catch (Throwable t) {
+                        t.printStackTrace();
+                    }
+                    cmdEvent.stateMask = event.stateMask;
+                    event.doit = false;
+                    try {
+                        handlerService.executeCommand(cmd, cmdEvent);
+                    } catch (ExecutionException e) {
+                        TerminalPlugin.getDefault().getLog().log(
+                                new Status(IStatus.ERROR, TerminalPlugin.PLUGIN_ID, e.getLocalizedMessage(), e));
+                    } catch (Exception e) {
+                        // ignore other exceptions from cmd execution
+                    }
+                }
+            }
+        }
 
-       @Override
-    public TerminalState getState() {
-               return fState;
-       }
+    }
+
+    @Override
+    public void setTerminalTitle(String title) {
+        fTerminalListener.setTerminalTitle(title);
+    }
 
+    @Override
+    public TerminalState getState() {
+        return fState;
+    }
 
-       @Override
+    @Override
     public void setState(TerminalState state) {
-               fState=state;
-               fTerminalListener.setState(state);
-               // enable the (blinking) cursor if the terminal is connected
-               runAsyncInDisplayThread(new Runnable() {
-                       @Override
+        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()) {
-                                       if (isConnected()) {
-                                               fCtlText.setCursorEnabled(true);
-                                       } else {
-                                               fCtlText.setCursorEnabled(false);
-                                               // Stop capturing all key events
-                                               fFocusListener.captureKeyEvents(false);
-                                       }
-                               }
-                       }
-               });
-       }
-       /**
-        * @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() != null && !PlatformUI.getWorkbench().getDisplay().isDisposed())
-                       PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
-               // else should not happen and we ignore it...
-       }
-
-       @Override
+                if (fCtlText != null && !fCtlText.isDisposed()) {
+                    if (isConnected()) {
+                        fCtlText.setCursorEnabled(true);
+                    } else {
+                        fCtlText.setCursorEnabled(false);
+                        // Stop capturing all key events
+                        fFocusListener.captureKeyEvents(false);
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * @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() != null && !PlatformUI.getWorkbench().getDisplay().isDisposed())
+            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$
-       }
+        if (getTerminalConnector() != null)
+            return getTerminalConnector().getSettingsSummary();
+        return ""; //$NON-NLS-1$
+    }
 
-       @Override
+    @Override
     public void setConnector(ITerminalConnector connector) {
-               fConnector=connector;
+        fConnector = connector;
 
-       }
-       @Override
+    }
+
+    @Override
     public ICommandInputField getCommandInputField() {
-               return fCommandInputField;
-       }
+        return fCommandInputField;
+    }
 
-       @Override
+    @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
+        if (fCommandInputField != null)
+            fCommandInputField.dispose();
+        fCommandInputField = inputField;
+        if (fCommandInputField != null)
+            fCommandInputField.createControl(fWndParent, this);
+        if (fWndParent.isVisible())
+            fWndParent.layout(true);
+    }
+
+    @Override
+    public void setLogOutputStream(FileOutputStream lOutputStream) {
+        if (fOutputStream != null) {
+            try {
+                fOutputStream.close();
+            } catch (IOException e) {
+                // ignore on purpose
+            }
+        }
+        fOutputStream = lOutputStream;
+        getTerminalConnector().setCaptureStream(fOutputStream);
+    }
+
+    @Override
     public int getBufferLineLimit() {
-               return fTerminalModel.getMaxHeight();
-       }
+        return fTerminalModel.getMaxHeight();
+    }
 
-       @Override
+    @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
+        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();
-       }
+        return fCtlText.isScrollLock();
+    }
 
-       @Override
+    @Override
     public void setScrollLock(boolean on) {
-               fCtlText.setScrollLock(on);
-       }
+        fCtlText.setScrollLock(on);
+    }
 
-       @Override
+    @Override
     public void setInvertedColors(boolean invert) {
-               fCtlText.setInvertedColors(invert);
-       }
+        fCtlText.setInvertedColors(invert);
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setConnectOnEnterIfClosed(boolean)
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#setConnectOnEnterIfClosed(boolean)
+     */
+    @Override
     public final void setConnectOnEnterIfClosed(boolean on) {
-               connectOnEnterIfClosed = on;
-       }
+        connectOnEnterIfClosed = on;
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isConnectOnEnterIfClosed()
-        */
-       @Override
+    /* (non-Javadoc)
+     * @see org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl#isConnectOnEnterIfClosed()
+     */
+    @Override
     public final boolean isConnectOnEnterIfClosed() {
-               return connectOnEnterIfClosed;
-       }
+        return connectOnEnterIfClosed;
+    }
 
-       @Override
+    @Override
     public void setVT100LineWrapping(boolean enable) {
-               getTerminalText().setVT100LineWrapping(enable);
-       }
+        getTerminalText().setVT100LineWrapping(enable);
+    }
 
-       @Override
+    @Override
     public boolean isVT100LineWrapping() {
-               return getTerminalText().isVT100LineWrapping();
-       }
+        return getTerminalText().isVT100LineWrapping();
+    }
 
-       @Override
+    @Override
     public void enableApplicationCursorKeys(boolean enable) {
-               fApplicationCursorKeys = enable;
-       }
-       
-       @Override
-       public void addMouseListener(ITerminalMouseListener listener) {
-           getCtlText().addTerminalMouseListener(listener);
-       }
-       
-       @Override
-       public void removeMouseListener(ITerminalMouseListener listener) {
-           getCtlText().removeTerminalMouseListener(listener);
-       }
+        fApplicationCursorKeys = enable;
+    }
+
+    @Override
+    public void addMouseListener(ITerminalMouseListener listener) {
+        getCtlText().addTerminalMouseListener(listener);
+    }
+
+    @Override
+    public void removeMouseListener(ITerminalMouseListener listener) {
+        getCtlText().removeTerminalMouseListener(listener);
+    }
 
 }
index 242726e..20c982f 100644 (file)
@@ -13,6 +13,7 @@
  *******************************************************************************/
 package org.eclipse.tm.internal.terminal.provisional.api;
 
+import java.io.FileOutputStream;
 import java.io.OutputStream;
 
 import org.eclipse.core.runtime.IAdaptable;
@@ -20,87 +21,66 @@ import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
 import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
 
 /**
- * A contributed connection type to manage a single connection.
- *
- * Implementations of this class are contributed through the
- * <code>org.eclipse.tm.terminal.control.connectors</code> extension point. This
- * class gives access to the static markup of a terminal connector extension as
- * well as providing the lifecycle management for the dynamically loaded
- * {@link TerminalConnectorImpl} instance, which performs the actual
- * communications. This pattern allows for lazy initialization, bundle
- * activation and class loading of the actual {@link TerminalConnectorImpl}
- * instance.
- *
- * Clients can get terminal connector instances from the
- * {@link TerminalConnectorExtension} class, or from
- * {@link ITerminalViewControl#getTerminalConnector()} when running inside an
- * active terminal widget.
- *
+ * A contributed connection type to manage a single connection. Implementations of this class are contributed through the <code>org.eclipse.tm.terminal.control.connectors</code> extension point. This
+ * class gives access to the static markup of a terminal connector extension as well as providing the lifecycle management for the dynamically loaded {@link TerminalConnectorImpl} instance, which
+ * performs the actual communications. This pattern allows for lazy initialization, bundle activation and class loading of the actual {@link TerminalConnectorImpl} instance. Clients can get terminal
+ * connector instances from the {@link TerminalConnectorExtension} class, or from {@link ITerminalViewControl#getTerminalConnector()} when running inside an active terminal widget.
  * @noimplement This interface is not intended to be implemented by clients.
  * @noextend This interface is not intended to be extended by clients.
- *
  * @author Michael Scharf
  *         <p>
- *         <strong>EXPERIMENTAL</strong>. This class or interface has been added
- *         as part of a work in progress. There is no guarantee that this API
- *         will work or that it will remain the same. Please do not use this API
- *         without consulting with the <a
- *         href="http://www.eclipse.org/tm/">Target Management</a> team.
+ *         <strong>EXPERIMENTAL</strong>. This class or interface has been added as part of a work in progress. There is no guarantee that this API will work or that it will remain the same. Please do
+ *         not use this API without consulting with the <a href="http://www.eclipse.org/tm/">Target Management</a> team.
  *         </p>
  */
 public interface ITerminalConnector extends IAdaptable {
-       /**
-        * @return an ID of this connector. The id from the plugin.xml.
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       String getId();
-
-       /**
-        * @return <code>null</code> the name (as specified in the plugin.xml)
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       String getName();
-
-       /**
-        * @return <code>True</code> if the connector is not visible in user
-        *         selections.
-        * @since org.eclipse.tm.terminal 3.0.1
-        */
-       boolean isHidden();
-
-       /**
-        * @return true if the {@link TerminalConnectorImpl} has been initialized.
-        * If there was an initialization error, {@link #getInitializationErrorMessage()}
-        * returns the error message.
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       boolean isInitialized();
-
-       /**
-        * This method initializes the connector if it is not initialized!
-        * If the connector was initialized successfully, <code>null</code> is
-        * returned. Otherwise an error message describing the problem is returned.
-        * @return <code>null</code> or a localized error message.
-        * @since org.eclipse.tm.terminal 2.0
-        */
-       String getInitializationErrorMessage();
-
-       /**
-        * Connect using the current state of the settings.
-        * @param control Used to inform the UI about state changes and messages from the connection.
-        */
-       void connect(ITerminalControl control);
-
-       /**
-        * Disconnect if connected. Else do nothing.
-        */
-       void disconnect();
-
-       /**
-        * @return true if a local echo is needed.
-        * TODO:Michael Scharf: this should be handed within the connection....
-        */
-       boolean isLocalEcho();
+    /**
+     * @return an ID of this connector. The id from the plugin.xml.
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    String getId();
+
+    /**
+     * @return <code>null</code> the name (as specified in the plugin.xml)
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    String getName();
+
+    /**
+     * @return <code>True</code> if the connector is not visible in user selections.
+     * @since org.eclipse.tm.terminal 3.0.1
+     */
+    boolean isHidden();
+
+    /**
+     * @return true if the {@link TerminalConnectorImpl} has been initialized. If there was an initialization error, {@link #getInitializationErrorMessage()} returns the error message.
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    boolean isInitialized();
+
+    /**
+     * This method initializes the connector if it is not initialized! If the connector was initialized successfully, <code>null</code> is returned. Otherwise an error message describing the problem
+     * is returned.
+     * @return <code>null</code> or a localized error message.
+     * @since org.eclipse.tm.terminal 2.0
+     */
+    String getInitializationErrorMessage();
+
+    /**
+     * Connect using the current state of the settings.
+     * @param control Used to inform the UI about state changes and messages from the connection.
+     */
+    void connect(ITerminalControl control);
+
+    /**
+     * Disconnect if connected. Else do nothing.
+     */
+    void disconnect();
+
+    /**
+     * @return true if a local echo is needed. TODO:Michael Scharf: this should be handed within the connection....
+     */
+    boolean isLocalEcho();
 
     /**
      * Notify the remote site that the size of the terminal has changed.
@@ -110,38 +90,37 @@ public interface ITerminalConnector extends IAdaptable {
     void setTerminalSize(int newWidth, int newHeight);
 
     /**
-     * @return the terminal to remote stream (bytes written to this stream will
-     * be sent to the remote site). For the stream in the other direction (remote to
-     * terminal see {@link ITerminalControl#getRemoteToTerminalOutputStream()}
-        * @since org.eclipse.tm.terminal 2.0
+     * @return the terminal to remote stream (bytes written to this stream will be sent to the remote site). For the stream in the other direction (remote to terminal see
+     *         {@link ITerminalControl#getRemoteToTerminalOutputStream()}
+     * @since org.eclipse.tm.terminal 2.0
      */
     OutputStream getTerminalToRemoteStream();
 
-       /**
-        * Load the state of this connection. Is typically called before
-        * {@link #connect(ITerminalControl)}.
-        *
-        * @param store a string based data store. Short keys like "foo" can be used to
-        * store the state of the connection.
-        */
-       void load(ISettingsStore store);
-
-       /**
-        * When the view or dialog containing the terminal is closed,
-        * the state of the connection is saved into the settings store <code>store</code>
-        * @param store
-        */
-       void save(ISettingsStore store);
-       
-       /**
-        * Set or reset the settings store to the default values.
-        */
-       void setDefaultSettings();
-
-       /**
-        * @return A string that represents the settings of the connection. This representation
-        * may be shown in the status line of the terminal view.
-        */
-       String getSettingsSummary();
+    /**
+     * Load the state of this connection. Is typically called before {@link #connect(ITerminalControl)}.
+     * @param store a string based data store. Short keys like "foo" can be used to store the state of the connection.
+     */
+    void load(ISettingsStore store);
+
+    /**
+     * When the view or dialog containing the terminal is closed, the state of the connection is saved into the settings store <code>store</code>
+     * @param store
+     */
+    void save(ISettingsStore store);
+
+    /**
+     * Set or reset the settings store to the default values.
+     */
+    void setDefaultSettings();
+
+    /**
+     * @return A string that represents the settings of the connection. This representation may be shown in the status line of the terminal view.
+     */
+    String getSettingsSummary();
+
+    /**
+     * Set the FileOutputStream value if null close outputStream(=stop capturing).
+     */
+    void setCaptureStream(FileOutputStream fOutputStream);
 
 }
index a358335..ff453c2 100644 (file)
@@ -19,134 +19,105 @@ import org.eclipse.tm.internal.terminal.provisional.api.Logger;
 import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
 
 /**
- * Abstract base class for all terminal connector implementations to be
- * registered via the <code>org.eclipse.tm.terminal.control.connectors</code>
- * extension point.
- *
+ * Abstract base class for all terminal connector implementations to be registered via the <code>org.eclipse.tm.terminal.control.connectors</code> extension point.
  * @since org.eclipse.tm.terminal 2.0
  */
 public abstract class TerminalConnectorImpl {
 
-       /**
-        * The TerminalControl associated with this connector.
-        * Required for advertising state changes when needed.
-        */
-       protected ITerminalControl fControl;
-
-       /**
-        * Initialize this connector. This is called once after the constructor, in
-        * order to perform any required initializations such as loading required
-        * native libraries. Any work that may lead to runtime exceptions should be
-        * done in this method rather than in the constructor.
-        *
-        * @throws Exception when the connector fails to initialize (due to missing
-        *             required libraries, for instance).
-        */
-       public void initialize() throws Exception {
-       }
-
-       /**
-        * Connect using the current state of the settings.
-        * 
-        * This method is designed to be overridden by actual implementations, in
-        * order to open the streams required for communicating with the remote
-        * side. Extenders must call <code>super.connect(control)</code> as the
-        * first thing they are doing.
-        * 
-        * @param control Used to inform the UI about state changes and messages
-        *            from the connection.
-        */
-       public void connect(ITerminalControl control) {
-               Logger.log("entered."); //$NON-NLS-1$
-               fControl = control;
-       }
-
-       /**
-        * Disconnect if connected. Else do nothing. Has to set the state of the
-        * {@link ITerminalControl} when finished disconnecting.
-        */
-       public final void disconnect() {
-               Logger.log("entered."); //$NON-NLS-1$
-               doDisconnect();
-               fControl.setState(TerminalState.CLOSED);
-       }
-
-       /**
-        * Disconnect if connected. Else do nothing. Clients should override to
-        * perform any extra work needed for disconnecting.
-        */
-       protected void doDisconnect() {
-               // Do nothing by default
-       }
+    /**
+     * The TerminalControl associated with this connector. Required for advertising state changes when needed.
+     */
+    protected ITerminalControl fControl;
+
+    /**
+     * Initialize this connector. This is called once after the constructor, in order to perform any required initializations such as loading required native libraries. Any work that may lead to
+     * runtime exceptions should be done in this method rather than in the constructor.
+     * @throws Exception when the connector fails to initialize (due to missing required libraries, for instance).
+     */
+    public void initialize() throws Exception {
+    }
+
+    /**
+     * Connect using the current state of the settings. This method is designed to be overridden by actual implementations, in order to open the streams required for communicating with the remote
+     * side. Extenders must call <code>super.connect(control)</code> as the first thing they are doing.
+     * @param control Used to inform the UI about state changes and messages from the connection.
+     */
+    public void connect(ITerminalControl control) {
+        Logger.log("entered."); //$NON-NLS-1$
+        fControl = control;
+    }
+
+    /**
+     * Disconnect if connected. Else do nothing. Has to set the state of the {@link ITerminalControl} when finished disconnecting.
+     */
+    public final void disconnect() {
+        Logger.log("entered."); //$NON-NLS-1$
+        doDisconnect();
+        fControl.setState(TerminalState.CLOSED);
+    }
+
+    /**
+     * Disconnect if connected. Else do nothing. Clients should override to perform any extra work needed for disconnecting.
+     */
+    protected void doDisconnect() {
+        // Do nothing by default
+    }
+
+    /**
+     * @return the terminal to remote stream (bytes written to this stream will be sent to the remote site). For the stream in the other direction (remote to terminal see
+     *         {@link ITerminalControl#getRemoteToTerminalOutputStream()}
+     */
+    abstract public OutputStream getTerminalToRemoteStream();
+
+    /**
+     * @return A string that represents the settings of the connection. This representation may be shown in the status line of the terminal view.
+     */
+    abstract public String getSettingsSummary();
 
     /**
-     * @return the terminal to remote stream (bytes written to this stream will
-     * be sent to the remote site). For the stream in the other direction (remote to
-     * terminal see {@link ITerminalControl#getRemoteToTerminalOutputStream()}
+     * Test if local echo is needed. The default implementation returns <code>false</code>. Override to modify this behavior.
+     * @return true if a local echo is needed. TODO:Michael Scharf: this should be handed within the connection....
      */
-       abstract public OutputStream getTerminalToRemoteStream();
-
-       /**
-        * @return A string that represents the settings of the connection. This representation
-        * may be shown in the status line of the terminal view.
-        */
-       abstract public String getSettingsSummary();
-
-       /**
-        * Test if local echo is needed. The default implementation returns
-        * <code>false</code>. Override to modify this behavior.
-        *
-        * @return true if a local echo is needed. TODO:Michael Scharf: this should
-        *         be handed within the connection....
-        */
-       public boolean isLocalEcho() {
-               return false;
-       }
-
-       /**
-        * Set or reset the settings store to the default values.
-        */
-       public void setDefaultSettings() {
-               // do nothing by default
-       }
-
-       /**
-        * Load the state or settings of this connection. Is typically called before
-        * {@link #connect(ITerminalControl)}.
-        *
-        * Connectors that have nothing to configure do not need to implement this.
-        * Those terminals that do have configuration need to override this method
-        * to load settings.
-        *
-        * @param store a string based data store. Short keys like "foo" can be used
-        *            to store the state of the connection.
-        */
-       public void load(ISettingsStore store) {
-               // do nothing by default
-       }
-
-       /**
-        * When the view or dialog containing the terminal is closed, the state of
-        * the connection is saved into the settings store <code>store</code>.
-        *
-        * Connectors that have no state or settings to persist do not need to
-        * override this. Others should override to persist their settings.
-        *
-        * @param store the store for persisting settings.
-        */
-       public void save(ISettingsStore store) {
-               // do nothing by default
-       }
+    public boolean isLocalEcho() {
+        return false;
+    }
 
     /**
-        * Notify the remote site that the size of the terminal has changed.
-        *
-        * Concrete connectors should override this if they have the possibility to
-        * inform the remote about changed terminal size.
-        *
-        * @param newWidth the new width in characters.
-        * @param newHeight the new height in characters.
-        */
-       public void setTerminalSize(int newWidth, int newHeight) {
-       }
+     * Set or reset the settings store to the default values.
+     */
+    public void setDefaultSettings() {
+        // do nothing by default
+    }
+
+    /**
+     * Load the state or settings of this connection. Is typically called before {@link #connect(ITerminalControl)}. Connectors that have nothing to configure do not need to implement this. Those
+     * terminals that do have configuration need to override this method to load settings.
+     * @param store a string based data store. Short keys like "foo" can be used to store the state of the connection.
+     */
+    public void load(ISettingsStore store) {
+        // do nothing by default
+    }
+
+    /**
+     * When the view or dialog containing the terminal is closed, the state of the connection is saved into the settings store <code>store</code>. Connectors that have no state or settings to persist
+     * do not need to override this. Others should override to persist their settings.
+     * @param store the store for persisting settings.
+     */
+    public void save(ISettingsStore store) {
+        // do nothing by default
+    }
+
+    /**
+     * Notify the remote site that the size of the terminal has changed. Concrete connectors should override this if they have the possibility to inform the remote about changed terminal size.
+     * @param newWidth the new width in characters.
+     * @param newHeight the new height in characters.
+     */
+    public void setTerminalSize(int newWidth, int newHeight) {
+    }
+
+    /**
+     * Set the FileOutputStream value if null close outputStream(=stop capturing).
+     */
+    public void setCaptureStream(OutputStream captureStream) {
+    }
 }
index cdb5d2f..619168a 100644 (file)
@@ -23,59 +23,60 @@ import org.eclipse.tm.terminal.view.ui.services.TerminalService;
  * Terminal tab default dispose listener implementation.
  */
 public class TabDisposeListener implements DisposeListener {
-       private final TabFolderManager parentTabFolderManager;
+    private final TabFolderManager parentTabFolderManager;
 
-       /**
-        * Constructor.
-        *
-        * @param parentTabFolderManager The parent tab folder manager. Must not be <code>null</code>
-        */
-       public TabDisposeListener(TabFolderManager parentTabFolderManager) {
-               Assert.isNotNull(parentTabFolderManager);
-               this.parentTabFolderManager = parentTabFolderManager;
-       }
+    /**
+     * Constructor.
+     * @param parentTabFolderManager The parent tab folder manager. Must not be <code>null</code>
+     */
+    public TabDisposeListener(TabFolderManager parentTabFolderManager) {
+        Assert.isNotNull(parentTabFolderManager);
+        this.parentTabFolderManager = parentTabFolderManager;
+    }
 
-       /**
-        * Returns the parent terminal console tab folder manager instance.
-        *
-        * @return The parent terminal console tab folder manager instance.
-        */
-       protected final TabFolderManager getParentTabFolderManager() {
-               return parentTabFolderManager;
-       }
+    /**
+     * Returns the parent terminal console tab folder manager instance.
+     * @return The parent terminal console tab folder manager instance.
+     */
+    protected final TabFolderManager getParentTabFolderManager() {
+        return parentTabFolderManager;
+    }
 
-       /* (non-Javadoc)
-        * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
-        */
-       @Override
-       public void widgetDisposed(DisposeEvent e) {
-               // If a tab item gets disposed, we have to dispose the terminal as well
-               if (e.getSource() instanceof CTabItem) {
-                       // Get the terminal control (if any) from the tab item
-                       Object candidate = ((CTabItem)e.getSource()).getData();
-                       if (candidate instanceof ITerminalViewControl) {
-                               ITerminalViewControl terminal = (ITerminalViewControl)candidate;
-                               // Keep the context menu from being disposed
-                               terminal.getControl().setMenu(null);
-                               terminal.disposeTerminal();
-                       }
-                       // Dispose the command input field handler
-                       parentTabFolderManager.disposeTabCommandFieldHandler((CTabItem)e.getSource());
-                       // Dispose the tab item control
-                       Control control = ((CTabItem) e.getSource()).getControl();
-                       if (control != null) control.dispose();
+    /* (non-Javadoc)
+     * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+     */
+    @Override
+    public void widgetDisposed(DisposeEvent e) {
+        // If a tab item gets disposed, we have to dispose the terminal as well
+        if (e.getSource() instanceof CTabItem) {
+            // Get the terminal control (if any) from the tab item
+            Object candidate = ((CTabItem) e.getSource()).getData();
+            if (candidate instanceof ITerminalViewControl) {
+                ITerminalViewControl terminal = (ITerminalViewControl) candidate;
+                // Keep the context menu from being disposed
+                terminal.getControl().setMenu(null);
+                terminal.disposeTerminal();
+            }
+            // Dispose the command input field handler
+            parentTabFolderManager.disposeTabCommandFieldHandler((CTabItem) e.getSource());
+            // Dispose the SaveLog handler
+            parentTabFolderManager.disposeSaveLogHandler((CTabItem) e.getSource());
+            // Dispose the tab item control
+            Control control = ((CTabItem) e.getSource()).getControl();
+            if (control != null)
+                control.dispose();
 
-                       // If all items got removed, we have to switch back to the empty page control
-                       if (parentTabFolderManager.getTabFolder() != null && parentTabFolderManager.getTabFolder().getItemCount() == 0) {
-                               parentTabFolderManager.getParentView().switchToEmptyPageControl();
-                       }
-                       // Fire selection changed event
-                       parentTabFolderManager.fireSelectionChanged();
-                       // Fire the terminal console disposed event
-                       ITerminalService service = TerminalServiceFactory.getService();
-                       if (service instanceof TerminalService) {
-                               ((TerminalService)service).fireTerminalTabEvent(TerminalService.TAB_DISPOSED, e.getSource(), ((CTabItem)e.getSource()).getData("customData")); //$NON-NLS-1$
-                       }
-               }
-       }
+            // If all items got removed, we have to switch back to the empty page control
+            if (parentTabFolderManager.getTabFolder() != null && parentTabFolderManager.getTabFolder().getItemCount() == 0) {
+                parentTabFolderManager.getParentView().switchToEmptyPageControl();
+            }
+            // Fire selection changed event
+            parentTabFolderManager.fireSelectionChanged();
+            // Fire the terminal console disposed event
+            ITerminalService service = TerminalServiceFactory.getService();
+            if (service instanceof TerminalService) {
+                ((TerminalService) service).fireTerminalTabEvent(TerminalService.TAB_DISPOSED, e.getSource(), ((CTabItem) e.getSource()).getData("customData")); //$NON-NLS-1$
+            }
+        }
+    }
 }
index 41e120b..545802c 100644 (file)
@@ -60,799 +60,850 @@ import org.eclipse.ui.PlatformUI;
  * Terminal tab folder manager.
  */
 public class TabFolderManager extends PlatformObject implements ISelectionProvider {
-       // Reference to the parent terminal consoles view
-       private final ITerminalsView parentView;
-       // Reference to the selection listener instance
-       private final SelectionListener selectionListener;
-
-       /**
-        * List of selection changed listeners.
-        */
-       private final List<ISelectionChangedListener> selectionChangedListeners = new ArrayList<ISelectionChangedListener>();
-
-       /**
-        * Map of tab command input field handler per tab item
-        */
-       private final Map<CTabItem, TabCommandFieldHandler> commandFieldHandler = new HashMap<CTabItem, TabCommandFieldHandler>();
-
-       /**
-        * The terminal control selection listener implementation.
-        */
-       private class TerminalControlSelectionListener implements DisposeListener, MouseListener {
-               private final ITerminalViewControl terminal;
-               private boolean selectMode;
-
-               /**
-                * Constructor.
-                *
-                * @param terminal The terminal control. Must not be <code>null</code>.
-                */
-               public TerminalControlSelectionListener(ITerminalViewControl terminal) {
-                       Assert.isNotNull(terminal);
-                       this.terminal = terminal;
-
-                       // Register ourself as the required listener
-                       terminal.getControl().addDisposeListener(this);
-                       terminal.getControl().addMouseListener(this);
-               }
-
-               /**
-                * Returns the associated terminal view control.
-                *
-                * @return The terminal view control.
-                */
-               protected final ITerminalViewControl getTerminal() {
-                       return terminal;
-               }
-
-               /* (non-Javadoc)
-                * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
-                */
-               @Override
-               public void widgetDisposed(DisposeEvent e) {
-                       // Widget got disposed, check if it is ours
-                       // If a tab item gets disposed, we have to dispose the terminal as well
-                       if (e.getSource().equals(terminal.getControl())) {
-                               // Remove as listener
-                               getTerminal().getControl().removeDisposeListener(this);
-                               getTerminal().getControl().removeMouseListener(this);
-                       }
-               }
-
-               /* (non-Javadoc)
-                * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
-                */
-               @Override
-               public void mouseDown(MouseEvent e) {
-                       // Left button down -> select mode starts
-                       if (e.button == 1) selectMode = true;
-               }
-
-               /* (non-Javadoc)
-                * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
-                */
-               @Override
-               public void mouseUp(MouseEvent e) {
-                       if (e.button == 1 && selectMode) {
-                               selectMode = false;
-                               // Fire a selection changed event with the terminal controls selection
-                       try {
-                           Display display = PlatformUI.getWorkbench().getDisplay();
-                           display.asyncExec(new Runnable() {
-                                               @Override
-                                               public void run() {
-                                                       fireSelectionChanged(new StructuredSelection(getTerminal().getSelection()));
-                                               }
-                                       });
-                       }
-                       catch (Exception ex) {
-                           // if display is disposed, silently ignore.
-                       }
-                       }
-               }
-
-               /* (non-Javadoc)
-                * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
-                */
-               @Override
-               public void mouseDoubleClick(MouseEvent e) {
-               }
-       }
-
-       /**
-        * Constructor.
-        *
-        * @param parentView The parent terminals console view. Must not be <code>null</code>.
-        */
-       public TabFolderManager(ITerminalsView parentView) {
-               super();
-               Assert.isNotNull(parentView);
-               this.parentView = parentView;
-
-               // Attach a selection listener to the tab folder
-               selectionListener = doCreateTabFolderSelectionListener(this);
-               if (getTabFolder() != null) getTabFolder().addSelectionListener(selectionListener);
-       }
-
-       /**
-        * Creates the terminal console tab folder selection listener instance.
-        *
-        * @param parent The parent terminal console tab folder manager. Must not be <code>null</code>.
-        * @return The selection listener instance.
-        */
-       protected TabFolderSelectionListener doCreateTabFolderSelectionListener(TabFolderManager parent) {
-               Assert.isNotNull(parent);
-               return new TabFolderSelectionListener(parent);
-       }
-
-       /**
-        * Returns the parent terminal consoles view.
-        *
-        * @return The terminal consoles view instance.
-        */
-       protected final ITerminalsView getParentView() {
-               return parentView;
-       }
-
-       /**
-        * Returns the tab folder associated with the parent view.
-        *
-        * @return The tab folder or <code>null</code>.
-        */
-       @SuppressWarnings("cast")
+    // Reference to the parent terminal consoles view
+    private final ITerminalsView parentView;
+    // Reference to the selection listener instance
+    private final SelectionListener selectionListener;
+
+    /**
+     * List of selection changed listeners.
+     */
+    private final List<ISelectionChangedListener> selectionChangedListeners = new ArrayList<ISelectionChangedListener>();
+
+    /**
+     * Map of tab command input field handler per tab item
+     */
+    private final Map<CTabItem, TabCommandFieldHandler> commandFieldHandler = new HashMap<CTabItem, TabCommandFieldHandler>();
+    /**
+     * Map of ToggleSaveLog handler per CTabItem
+     */
+    private final Map<CTabItem, ToggleSaveLogHandler> saveLogHandlerMap = new HashMap<CTabItem, ToggleSaveLogHandler>();
+
+    /**
+     * The terminal control selection listener implementation.
+     */
+    private class TerminalControlSelectionListener implements DisposeListener, MouseListener {
+        private final ITerminalViewControl terminal;
+        private boolean selectMode;
+
+        /**
+         * Constructor.
+         * @param terminal The terminal control. Must not be <code>null</code>.
+         */
+        public TerminalControlSelectionListener(ITerminalViewControl terminal) {
+            Assert.isNotNull(terminal);
+            this.terminal = terminal;
+
+            // Register ourself as the required listener
+            terminal.getControl().addDisposeListener(this);
+            terminal.getControl().addMouseListener(this);
+        }
+
+        /**
+         * Returns the associated terminal view control.
+         * @return The terminal view control.
+         */
+        protected final ITerminalViewControl getTerminal() {
+            return terminal;
+        }
+
+        /* (non-Javadoc)
+         * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+         */
+        @Override
+        public void widgetDisposed(DisposeEvent e) {
+            // Widget got disposed, check if it is ours
+            // If a tab item gets disposed, we have to dispose the terminal as well
+            if (e.getSource().equals(terminal.getControl())) {
+                // Remove as listener
+                getTerminal().getControl().removeDisposeListener(this);
+                getTerminal().getControl().removeMouseListener(this);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+         */
+        @Override
+        public void mouseDown(MouseEvent e) {
+            // Left button down -> select mode starts
+            if (e.button == 1)
+                selectMode = true;
+        }
+
+        /* (non-Javadoc)
+         * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+         */
+        @Override
+        public void mouseUp(MouseEvent e) {
+            if (e.button == 1 && selectMode) {
+                selectMode = false;
+                // Fire a selection changed event with the terminal controls selection
+                try {
+                    Display display = PlatformUI.getWorkbench().getDisplay();
+                    display.asyncExec(new Runnable() {
+                        @Override
+                        public void run() {
+                            fireSelectionChanged(new StructuredSelection(getTerminal().getSelection()));
+                        }
+                    });
+                } catch (Exception ex) {
+                    // if display is disposed, silently ignore.
+                }
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+         */
+        @Override
+        public void mouseDoubleClick(MouseEvent e) {
+        }
+    }
+
+    /**
+     * Constructor.
+     * @param parentView The parent terminals console view. Must not be <code>null</code>.
+     */
+    public TabFolderManager(ITerminalsView parentView) {
+        super();
+        Assert.isNotNull(parentView);
+        this.parentView = parentView;
+
+        // Attach a selection listener to the tab folder
+        selectionListener = doCreateTabFolderSelectionListener(this);
+        if (getTabFolder() != null)
+            getTabFolder().addSelectionListener(selectionListener);
+    }
+
+    /**
+     * Creates the terminal console tab folder selection listener instance.
+     * @param parent The parent terminal console tab folder manager. Must not be <code>null</code>.
+     * @return The selection listener instance.
+     */
+    protected TabFolderSelectionListener doCreateTabFolderSelectionListener(TabFolderManager parent) {
+        Assert.isNotNull(parent);
+        return new TabFolderSelectionListener(parent);
+    }
+
+    /**
+     * Returns the parent terminal consoles view.
+     * @return The terminal consoles view instance.
+     */
+    protected final ITerminalsView getParentView() {
+        return parentView;
+    }
+
+    /**
+     * Returns the tab folder associated with the parent view.
+     * @return The tab folder or <code>null</code>.
+     */
+    @SuppressWarnings("cast")
     protected final CTabFolder getTabFolder() {
-               return (CTabFolder) getParentView().getAdapter(CTabFolder.class);
-       }
-
-       /**
-        * Returns the selection changed listeners currently registered.
-        *
-        * @return The registered selection changed listeners or an empty array.
-        */
-       protected final ISelectionChangedListener[] getSelectionChangedListeners() {
-               return selectionChangedListeners.toArray(new ISelectionChangedListener[selectionChangedListeners.size()]);
-       }
-
-       /**
-        * Dispose the tab folder manager instance.
-        */
-       public void dispose() {
-               // Dispose the selection listener
-               if (getTabFolder() != null && !getTabFolder().isDisposed()) getTabFolder().removeSelectionListener(selectionListener);
-               // Dispose the tab command field handler
-               for (TabCommandFieldHandler handler : commandFieldHandler.values()) {
-                       handler.dispose();
-               }
-               commandFieldHandler.clear();
-       }
-
-       /**
-        * Creates a new tab item with the given title and connector.
-        *
-        * @param title The tab title. Must not be <code>null</code>.
-        * @param encoding The terminal encoding or <code>null</code>.
-        * @param connector The terminal connector. Must not be <code>null</code>.
-        * @param data The custom terminal data node or <code>null</code>.
-        * @param flags The flags controlling how the console is opened or <code>null</code> to use defaults.
-        *
-        * @return The created tab item or <code>null</code> if failed.
-        */
-       @SuppressWarnings({ "unused", "cast" })
-       public CTabItem createTabItem(String title, String encoding, ITerminalConnector connector, Object data, Map<String, Boolean> flags) {
-               Assert.isNotNull(title);
-               Assert.isNotNull(connector);
-
-               // The result tab item
-               CTabItem item = null;
-
-               // Get the tab folder from the parent viewer
-               CTabFolder tabFolder = getTabFolder();
-               if (tabFolder != null) {
-                       // Generate a unique title string for the new tab item (must be called before creating the item itself)
-                       title = makeUniqueTitle(title, tabFolder);
-                       // Create the tab item
-                       item = new CTabItem(tabFolder, SWT.CLOSE);
-                       // Set the tab item title
-                       item.setText(title);
-                       // Set the tab icon
-                       Image image = getTabItemImage(connector, data);
-                       if (image != null) item.setImage(image);
-
-                       // Setup the tab item listeners
-                       setupTerminalTabListeners(item);
-
-                       // Create the composite to create the terminal control within
-                       Composite composite = new Composite(tabFolder, SWT.NONE);
-                       composite.setLayout(new FillLayout());
-                       // Associate the composite with the tab item
-                       item.setControl(composite);
-
-                       // Refresh the layout
-                       tabFolder.getParent().layout(true);
-
-                       // Create the terminal control
-                       ITerminalViewControl terminal = TerminalViewControlFactory.makeControl(doCreateTerminalTabTerminalListener(this, item), composite, new ITerminalConnector[] { connector }, true);
-                       if (terminal instanceof ITerminalControl) {
-                               Object value = flags != null ? flags.get(ITerminalsConnectorConstants.PROP_DATA_NO_RECONNECT) : null;
-                               boolean noReconnect = value instanceof Boolean ? ((Boolean)value).booleanValue() : false;
-                               ((ITerminalControl)terminal).setConnectOnEnterIfClosed(!noReconnect);
-                       }
-
-                       // Add middle mouse button paste support
-                       addMiddleMouseButtonPasteSupport(terminal);
-                       // Add the "selection" listener to the terminal control
-                       new TerminalControlSelectionListener(terminal);
-                       // Configure the terminal encoding
-                       try { terminal.setEncoding(encoding); } catch (UnsupportedEncodingException e) { /* ignored on purpose */ }
-                       // Associated the terminal with the tab item
-                       item.setData(terminal);
-                       // Associated the custom data node with the tab item (if any)
-                       if (data != null) item.setData("customData", data); //$NON-NLS-1$
-
-                       // Overwrite the text canvas help id
-                       String contextHelpId = getParentView().getContextHelpId();
-                       if (contextHelpId != null) {
-                               PlatformUI.getWorkbench().getHelpSystem().setHelp(terminal.getControl(), contextHelpId);
-                       }
-
-                       // Set the context menu
-                       TabFolderMenuHandler menuHandler = (TabFolderMenuHandler) getParentView().getAdapter(TabFolderMenuHandler.class);
-                       if (menuHandler != null) {
-                               Menu menu = (Menu)menuHandler.getAdapter(Menu.class);
-                               if (menu != null) {
-                                       // One weird occurrence of IllegalArgumentException: Widget has wrong parent.
-                                       // Inspecting the code, this seem extremely unlikely. The terminal is created
-                                       // from a composite parent, the composite parent from the tab folder and the menu
-                                       // from the tab folder. Means, at the end all should have the same menu shell, shouldn't they?
-                                       try {
-                                               terminal.getControl().setMenu(menu);
-                                       } catch (IllegalArgumentException e) {
-                                               // Log exception only if debug mode is set to 1.
-                                               if (UIPlugin.getTraceHandler().isSlotEnabled(1, null)) {
-                                                       e.printStackTrace();
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Select the created item within the tab folder
-                       tabFolder.setSelection(item);
-
-                       // Set the connector
-                       terminal.setConnector(connector);
-
-                       // And connect the terminal
-                       terminal.connectTerminal();
-
-                       // Fire selection changed event
-                       fireSelectionChanged();
-               }
-
-               // Return the create tab item finally.
-               return item;
-       }
-
-       /**
-        * Used for DnD of terminal tab items between terminal views
-        * <p>
-        * Create a new tab item in the "dropped" terminal view using the
-        * information stored in the given item.
-        *
-        * @param oldItem The old dragged tab item. Must not be <code>null</code>.
-        * @return The new dropped tab item.
-        */
-       @SuppressWarnings({ "unchecked", "cast" })
+        return (CTabFolder) getParentView().getAdapter(CTabFolder.class);
+    }
+
+    /**
+     * Returns the selection changed listeners currently registered.
+     * @return The registered selection changed listeners or an empty array.
+     */
+    protected final ISelectionChangedListener[] getSelectionChangedListeners() {
+        return selectionChangedListeners.toArray(new ISelectionChangedListener[selectionChangedListeners.size()]);
+    }
+
+    /**
+     * Dispose the tab folder manager instance.
+     */
+    public void dispose() {
+        // Dispose the selection listener
+        if (getTabFolder() != null && !getTabFolder().isDisposed())
+            getTabFolder().removeSelectionListener(selectionListener);
+        // Dispose the tab command field handler
+        for (TabCommandFieldHandler handler : commandFieldHandler.values()) {
+            handler.dispose();
+        }
+        commandFieldHandler.clear();
+
+        /**
+         * Dispose the saveLog Handler
+         */
+        for (ToggleSaveLogHandler handler : saveLogHandlerMap.values()) {
+            handler.dispose();
+        }
+        saveLogHandlerMap.clear();
+    }
+
+    /**
+     * Creates a new tab item with the given title and connector.
+     * @param title The tab title. Must not be <code>null</code>.
+     * @param encoding The terminal encoding or <code>null</code>.
+     * @param connector The terminal connector. Must not be <code>null</code>.
+     * @param data The custom terminal data node or <code>null</code>.
+     * @param flags The flags controlling how the console is opened or <code>null</code> to use defaults.
+     * @return The created tab item or <code>null</code> if failed.
+     */
+    @SuppressWarnings({ "unused", "cast" })
+    public CTabItem createTabItem(String title, String encoding, ITerminalConnector connector, Object data, Map<String, Boolean> flags) {
+        Assert.isNotNull(title);
+        Assert.isNotNull(connector);
+
+        // The result tab item
+        CTabItem item = null;
+
+        // Get the tab folder from the parent viewer
+        CTabFolder tabFolder = getTabFolder();
+        if (tabFolder != null) {
+            // Generate a unique title string for the new tab item (must be called before creating the item itself)
+            title = makeUniqueTitle(title, tabFolder);
+            // Create the tab item
+            item = new CTabItem(tabFolder, SWT.CLOSE);
+            // Set the tab item title
+            item.setText(title);
+            // Set the tab icon
+            Image image = getTabItemImage(connector, data);
+            if (image != null)
+                item.setImage(image);
+
+            // Setup the tab item listeners
+            setupTerminalTabListeners(item);
+
+            // Create the composite to create the terminal control within
+            Composite composite = new Composite(tabFolder, SWT.NONE);
+            composite.setLayout(new FillLayout());
+            // Associate the composite with the tab item
+            item.setControl(composite);
+
+            // Refresh the layout
+            tabFolder.getParent().layout(true);
+
+            // Create the terminal control
+            ITerminalViewControl terminal = TerminalViewControlFactory.makeControl(doCreateTerminalTabTerminalListener(this, item), composite, new ITerminalConnector[] { connector }, true);
+            if (terminal instanceof ITerminalControl) {
+                Object value = flags != null ? flags.get(ITerminalsConnectorConstants.PROP_DATA_NO_RECONNECT) : null;
+                boolean noReconnect = value instanceof Boolean ? ((Boolean) value).booleanValue() : false;
+                ((ITerminalControl) terminal).setConnectOnEnterIfClosed(!noReconnect);
+            }
+
+            // Add middle mouse button paste support
+            addMiddleMouseButtonPasteSupport(terminal);
+            // Add the "selection" listener to the terminal control
+            new TerminalControlSelectionListener(terminal);
+            // Configure the terminal encoding
+            try {
+                terminal.setEncoding(encoding);
+            } catch (UnsupportedEncodingException e) {
+                /* ignored on purpose */ }
+            // Associated the terminal with the tab item
+            item.setData(terminal);
+            // Associated the custom data node with the tab item (if any)
+            if (data != null)
+                item.setData("customData", data); //$NON-NLS-1$
+
+            // Overwrite the text canvas help id
+            String contextHelpId = getParentView().getContextHelpId();
+            if (contextHelpId != null) {
+                PlatformUI.getWorkbench().getHelpSystem().setHelp(terminal.getControl(), contextHelpId);
+            }
+
+            // Set the context menu
+            TabFolderMenuHandler menuHandler = (TabFolderMenuHandler) getParentView().getAdapter(TabFolderMenuHandler.class);
+            if (menuHandler != null) {
+                Menu menu = (Menu) menuHandler.getAdapter(Menu.class);
+                if (menu != null) {
+                    // One weird occurrence of IllegalArgumentException: Widget has wrong parent.
+                    // Inspecting the code, this seem extremely unlikely. The terminal is created
+                    // from a composite parent, the composite parent from the tab folder and the menu
+                    // from the tab folder. Means, at the end all should have the same menu shell, shouldn't they?
+                    try {
+                        terminal.getControl().setMenu(menu);
+                    } catch (IllegalArgumentException e) {
+                        // Log exception only if debug mode is set to 1.
+                        if (UIPlugin.getTraceHandler().isSlotEnabled(1, null)) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+
+            // Select the created item within the tab folder
+            tabFolder.setSelection(item);
+
+            // Set the connector
+            terminal.setConnector(connector);
+
+            // And connect the terminal
+            terminal.connectTerminal();
+
+            // Fire selection changed event
+            fireSelectionChanged();
+        }
+
+        // Return the create tab item finally.
+        return item;
+    }
+
+    /**
+     * Used for DnD of terminal tab items between terminal views
+     * <p>
+     * Create a new tab item in the "dropped" terminal view using the information stored in the given item.
+     * @param oldItem The old dragged tab item. Must not be <code>null</code>.
+     * @return The new dropped tab item.
+     */
+    @SuppressWarnings({ "unchecked", "cast" })
     public CTabItem cloneTabItemAfterDrop(CTabItem oldItem) {
-               Assert.isNotNull(oldItem);
-
-               ITerminalViewControl terminal = (ITerminalViewControl)oldItem.getData();
-               ITerminalConnector connector = terminal.getTerminalConnector();
-               Object data = oldItem.getData("customData"); //$NON-NLS-1$
-               Map<String, Object> properties = (Map<String, Object>)oldItem.getData("properties"); //$NON-NLS-1$
-               String title = oldItem.getText();
-
-               // The result tab item
-               CTabItem item = null;
-
-               // Get the tab folder from the parent viewer
-               CTabFolder tabFolder = getTabFolder();
-               if (tabFolder != null) {
-                       // Generate a unique title string for the new tab item (must be called before creating the item itself)
-                       title = makeUniqueTitle(title, tabFolder);
-                       // Create the tab item
-                       item = new CTabItem(tabFolder, SWT.CLOSE);
-                       // Set the tab item title
-                       item.setText(title);
-                       // Set the tab icon
-                       Image image = getTabItemImage(connector, data);
-                       if (image != null) item.setImage(image);
-
-                       // Setup the tab item listeners
-                       setupTerminalTabListeners(item);
-                       // Move the terminal listener to the new item
-                       TabTerminalListener.move(oldItem, item);
-
-                       // Create the composite to create the terminal control within
-                       Composite composite = new Composite(tabFolder, SWT.NONE);
-                       composite.setLayout(new FillLayout());
-                       // Associate the composite with the tab item
-                       item.setControl(composite);
-
-                       // Refresh the layout
-                       tabFolder.getParent().layout(true);
-
-                       // Remember terminal state
-                       TerminalState oldState = terminal.getState();
-
-                       // Keep the context menu from being disposed
-                       terminal.getControl().setMenu(null);
-
-                       // change the "parent".
-                       Assert.isTrue(terminal instanceof ITerminalControl);
-                       ((ITerminalControl)terminal).setupTerminal(composite);
-
-                       // Add middle mouse button paste support
-                       addMiddleMouseButtonPasteSupport(terminal);
-
-                       item.setData(terminal);
-
-                       // Associate the custom data node with the tab item (if any)
-                       if (data != null) item.setData("customData", data); //$NON-NLS-1$
-                       // Associate the properties with the tab item (if any)
-                       if (properties != null) item.setData("properties", properties); //$NON-NLS-1$
-
-                       // Overwrite the text canvas help id
-                       String contextHelpId = getParentView().getContextHelpId();
-                       if (contextHelpId != null) {
-                               PlatformUI.getWorkbench().getHelpSystem().setHelp(terminal.getControl(), contextHelpId);
-                       }
-
-                       // Set the context menu
-                       TabFolderMenuHandler menuHandler = (TabFolderMenuHandler) getParentView().getAdapter(TabFolderMenuHandler.class);
-                       if (menuHandler != null) {
-                               Menu menu = (Menu)menuHandler.getAdapter(Menu.class);
-                               if (menu != null) {
-                                       // One weird occurrence of IllegalArgumentException: Widget has wrong parent.
-                                       // Inspecting the code, this seem extremely unlikely. The terminal is created
-                                       // from a composite parent, the composite parent from the tab folder and the menu
-                                       // from the tab folder. Means, at the end all should have the same menu shell, shouldn't they?
-                                       try {
-                                               terminal.getControl().setMenu(menu);
-                                       } catch (IllegalArgumentException e) {
-                                               // Log exception only if debug mode is set to 1.
-                                               if (UIPlugin.getTraceHandler().isSlotEnabled(1, null)) {
-                                                       e.printStackTrace();
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Select the created item within the tab folder
-                       tabFolder.setSelection(item);
-
-                       // Set the connector
-                       terminal.setConnector(connector);
-
-                       // needed to get the focus and cursor
-                       Assert.isTrue(terminal instanceof ITerminalControl);
-                       ((ITerminalControl)terminal).setState(oldState);
-
-                       // Fire selection changed event
-                       fireSelectionChanged();
-               }
-
-               // Return the create tab item finally.
-               return item;
-       }
-
-
-       protected void addMiddleMouseButtonPasteSupport(final ITerminalViewControl terminal) {
-               terminal.getControl().addMouseListener(new MouseAdapter(){
-                       @Override
+        Assert.isNotNull(oldItem);
+
+        ITerminalViewControl terminal = (ITerminalViewControl) oldItem.getData();
+        ITerminalConnector connector = terminal.getTerminalConnector();
+        Object data = oldItem.getData("customData"); //$NON-NLS-1$
+        Map<String, Object> properties = (Map<String, Object>) oldItem.getData("properties"); //$NON-NLS-1$
+        String title = oldItem.getText();
+
+        // The result tab item
+        CTabItem item = null;
+
+        // Get the tab folder from the parent viewer
+        CTabFolder tabFolder = getTabFolder();
+        if (tabFolder != null) {
+            // Generate a unique title string for the new tab item (must be called before creating the item itself)
+            title = makeUniqueTitle(title, tabFolder);
+            // Create the tab item
+            item = new CTabItem(tabFolder, SWT.CLOSE);
+            // Set the tab item title
+            item.setText(title);
+            // Set the tab icon
+            Image image = getTabItemImage(connector, data);
+            if (image != null)
+                item.setImage(image);
+
+            // Setup the tab item listeners
+            setupTerminalTabListeners(item);
+            // Move the terminal listener to the new item
+            TabTerminalListener.move(oldItem, item);
+
+            // Create the composite to create the terminal control within
+            Composite composite = new Composite(tabFolder, SWT.NONE);
+            composite.setLayout(new FillLayout());
+            // Associate the composite with the tab item
+            item.setControl(composite);
+
+            // Refresh the layout
+            tabFolder.getParent().layout(true);
+
+            // Remember terminal state
+            TerminalState oldState = terminal.getState();
+
+            // Keep the context menu from being disposed
+            terminal.getControl().setMenu(null);
+
+            // change the "parent".
+            Assert.isTrue(terminal instanceof ITerminalControl);
+            ((ITerminalControl) terminal).setupTerminal(composite);
+
+            // Add middle mouse button paste support
+            addMiddleMouseButtonPasteSupport(terminal);
+
+            item.setData(terminal);
+
+            // Associate the custom data node with the tab item (if any)
+            if (data != null)
+                item.setData("customData", data); //$NON-NLS-1$
+            // Associate the properties with the tab item (if any)
+            if (properties != null)
+                item.setData("properties", properties); //$NON-NLS-1$
+
+            // Overwrite the text canvas help id
+            String contextHelpId = getParentView().getContextHelpId();
+            if (contextHelpId != null) {
+                PlatformUI.getWorkbench().getHelpSystem().setHelp(terminal.getControl(), contextHelpId);
+            }
+
+            // Set the context menu
+            TabFolderMenuHandler menuHandler = (TabFolderMenuHandler) getParentView().getAdapter(TabFolderMenuHandler.class);
+            if (menuHandler != null) {
+                Menu menu = (Menu) menuHandler.getAdapter(Menu.class);
+                if (menu != null) {
+                    // One weird occurrence of IllegalArgumentException: Widget has wrong parent.
+                    // Inspecting the code, this seem extremely unlikely. The terminal is created
+                    // from a composite parent, the composite parent from the tab folder and the menu
+                    // from the tab folder. Means, at the end all should have the same menu shell, shouldn't they?
+                    try {
+                        terminal.getControl().setMenu(menu);
+                    } catch (IllegalArgumentException e) {
+                        // Log exception only if debug mode is set to 1.
+                        if (UIPlugin.getTraceHandler().isSlotEnabled(1, null)) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+
+            // Select the created item within the tab folder
+            tabFolder.setSelection(item);
+
+            // Set the connector
+            terminal.setConnector(connector);
+
+            // needed to get the focus and cursor
+            Assert.isTrue(terminal instanceof ITerminalControl);
+            ((ITerminalControl) terminal).setState(oldState);
+
+            // Fire selection changed event
+            fireSelectionChanged();
+        }
+
+        // Return the create tab item finally.
+        return item;
+    }
+
+    protected void addMiddleMouseButtonPasteSupport(final ITerminalViewControl terminal) {
+        terminal.getControl().addMouseListener(new MouseAdapter() {
+            @Override
             public void mouseDown(MouseEvent e) {
-                               // paste when the middle button is clicked
-                               if (e.button == 2) {
-                                       Clipboard clipboard = terminal.getClipboard();
-                                       if (clipboard.isDisposed()) return;
-                                       int clipboardType = DND.SELECTION_CLIPBOARD;
-                                       if (clipboard.getAvailableTypes(clipboardType).length == 0)
-                                               // use normal clipboard if selection clipboard is not available
-                                               clipboardType = DND.CLIPBOARD;
-                                       String text = (String) clipboard.getContents(TextTransfer.getInstance(), clipboardType);
-                                       if (text != null && text.length() > 0)
-                                               terminal.pasteString(text);
-                               }
-                       }
-               });
-    }
-
-       /**
-        * Generate a unique title string based on the given proposal.
-        *
-        * @param proposal The proposal. Must not be <code>null</code>.
-        * @return The unique title string.
-        */
-       protected String makeUniqueTitle(String proposal, CTabFolder tabFolder) {
-               Assert.isNotNull(proposal);
-               Assert.isNotNull(tabFolder);
-
-               String title = proposal;
-               int index = 0;
-
-               // Loop all existing tab items and check the titles. We have to remember
-               // all found titles as modifying the proposal might in turn conflict again
-               // with the title of a tab already checked.
-               List<String> titles = new ArrayList<String>();
-               for (CTabItem item : tabFolder.getItems()) {
-                       // Get the tab item title
-                       titles.add(item.getText());
-               }
-               // Make the proposal unique be appending (<n>) against all known titles.
-               while (titles.contains(title)) title = proposal + " (" + ++index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
-
-               return title;
-       }
-
-       /**
-        * Setup the terminal console tab item listeners.
-        *
-        * @param item The tab item. Must not be <code>null</code>.
-        */
-       protected void setupTerminalTabListeners(final CTabItem item) {
-               Assert.isNotNull(item);
-
-               // Create and associate the disposal listener
-               DisposeListener disposeListener = doCreateTerminalTabDisposeListener(this);
-
-               // store the listener to make access easier e.g. needed in DnD
-               item.setData("disposeListener", disposeListener); //$NON-NLS-1$
-               item.addDisposeListener(disposeListener);
-       }
-
-       /**
-        * Creates a new terminal console tab terminal listener instance.
-        *
-        * @param tabFolderManager The tab folder manager. Must not be <code>null</code>.
-        * @param item The tab item. Must not be <code>null</code>.
-        *
-        * @return The terminal listener instance.
-        */
-       protected ITerminalListener doCreateTerminalTabTerminalListener(TabFolderManager tabFolderManager, CTabItem item) {
-               Assert.isNotNull(item);
-               return new TabTerminalListener(tabFolderManager, item);
-       }
-
-       /**
-        * Creates a new terminal console tab dispose listener instance.
-        *
-        * @param parent The parent terminal console tab folder manager. Must not be <code>null</code>.
-        * @return The dispose listener instance.
-        */
-       protected DisposeListener doCreateTerminalTabDisposeListener(TabFolderManager parent) {
-               Assert.isNotNull(parent);
-               return new TabDisposeListener(parent);
-       }
-
-       /**
-        * Returns the tab item image.
-        *
-        * @param connector The terminal connector. Must not be <code>null</code>.
-        * @param data The custom terminal data node or <code>null</code>.
-        *
-        * @return The tab item image or <code>null</code>.
-        */
-       protected Image getTabItemImage(ITerminalConnector connector, Object data) {
-               Assert.isNotNull(connector);
-               return UIPlugin.getImage(ImageConsts.VIEW_Terminals);
-       }
-
-       /**
-        * Lookup a tab item with the given title and the given terminal connector.
-        * <p>
-        * <b>Note:</b> The method will handle unified tab item titles itself.
-        *
-        * @param title The tab item title. Must not be <code>null</code>.
-        * @param connector The terminal connector. Must not be <code>null</code>.
-        * @param data The custom terminal data node or <code>null</code>.
-        *
-        * @return The corresponding tab item or <code>null</code>.
-        */
-       public CTabItem findTabItem(String title, ITerminalConnector connector, Object data) {
-               Assert.isNotNull(title);
-               Assert.isNotNull(connector);
-
-               // Get the tab folder
-               CTabFolder tabFolder = getTabFolder();
-               if (tabFolder == null) return null;
-
-               // Loop all existing tab items and try to find a matching title
-               for (CTabItem item : tabFolder.getItems()) {
-                       // Disposed items cannot be matched
-                       if (item.isDisposed()) continue;
-                       // Get the title from the current tab item
-                       String itemTitle = item.getText();
-                       // The terminal console state might be signaled to the user via the
-                       // terminal console tab title. Filter out any prefix "<.*>\s*".
-                       itemTitle = itemTitle.replaceFirst("^<.*>\\s*", ""); //$NON-NLS-1$ //$NON-NLS-2$
-                       if (itemTitle.startsWith(title)) {
-                               // The title string matches -> double check with the terminal connector
-                               ITerminalViewControl terminal = (ITerminalViewControl)item.getData();
-                               ITerminalConnector connector2 = terminal.getTerminalConnector();
-                               // If the connector id and name matches -> check on the settings
-                               if (connector.getId().equals(connector2.getId()) && connector.getName().equals(connector2.getName())) {
-                                       if (!connector.isInitialized()) {
-                                               // an uninitialized connector does not yield a sensible summary
-                                               return item;
-                                       }
-                                       String summary = connector.getSettingsSummary();
-                                       String summary2 = connector2.getSettingsSummary();
-                                       // If we have matching settings -> we've found the matching item
-                                       if (summary.equals(summary2)) return item;
-                               }
-                       }
-               }
-
-               return null;
-       }
-
-       /**
-        * Make the given tab item the active tab and bring the tab to the top.
-        *
-        * @param item The tab item. Must not be <code>null</code>.
-        */
-       public void bringToTop(CTabItem item) {
-               Assert.isNotNull(item);
-
-               // Get the tab folder
-               CTabFolder tabFolder = getTabFolder();
-               if (tabFolder == null) return;
-
-               // Set the given tab item as selection to the tab folder
-               tabFolder.setSelection(item);
-               // Fire selection changed event
-               fireSelectionChanged();
-       }
-
-       /**
-        * Returns the currently active tab.
-        *
-        * @return The active tab item or <code>null</code> if none.
-        */
-       public CTabItem getActiveTabItem() {
-               // Get the tab folder
-               CTabFolder tabFolder = getTabFolder();
-               if (tabFolder == null) return null;
-
-               return tabFolder.getSelection();
-       }
-
-       /**
-        * Remove all terminated tab items.
-        */
-       public void removeTerminatedItems() {
-               // Get the tab folder
-               CTabFolder tabFolder = getTabFolder();
-               if (tabFolder == null) return;
-
-               // Loop the items and check for terminated status
-               for (CTabItem item: tabFolder.getItems()) {
-                       // Disposed items cannot be matched
-                       if (item.isDisposed()) continue;
-                       // Check if the item is terminated
-                       if (isTerminatedTabItem(item)) {
-                               // item is terminated -> dispose
-                               item.dispose();
-                       }
-               }
-       }
-
-       /**
-        * Checks if the given tab item represents a terminated console. Subclasses may
-        * overwrite this method to extend the definition of terminated.
-        *
-        * @param item The tab item or <code>null</code>.
-        * @return <code>True</code> if the tab item represents a terminated console, <code>false</code> otherwise.
-        */
-       protected boolean isTerminatedTabItem(CTabItem item) {
-               // Null items or disposed items cannot be matched
-               if (item == null || item.isDisposed()) return false;
-
-               // First, match the item title. If it contains "<terminated>", the item can be removed
-               String itemTitle = item.getText();
-               if (itemTitle != null && itemTitle.contains("<terminated>")) { //$NON-NLS-1$
-                       return true;
-               }
-               // Second, check if the associated terminal control is closed
-               // The title string matches -> double check with the terminal connector
-               ITerminalViewControl terminal = (ITerminalViewControl)item.getData();
-               if (terminal != null && terminal.getState() == TerminalState.CLOSED) {
-                       return true;
-               }
-
-               return false;
-       }
-
-       /**
-        * Returns the command input field handler for the given tab item.
-        *
-        * @param item The tab item or <code>null</code>.
-        * @return The command input field handler or <code>null</code>.
-        */
-       public final TabCommandFieldHandler getTabCommandFieldHandler(CTabItem item) {
-               // Null items or disposed items cannot be matched
-               if (item == null || item.isDisposed()) return null;
-
-               TabCommandFieldHandler handler = commandFieldHandler.get(item);
-               if (handler == null) {
-                       handler = createTabCommandFieldHandler(this, item);
-                       Assert.isNotNull(handler);
-                       commandFieldHandler.put(item, handler);
-               }
-               return handler;
-       }
-
-       /**
-        * Create the command input field handler for the given tab item.
-        *
-        * @param tabFolderManager The parent tab folder manager. Must not be <code>null</code>
-        * @param item The associated tab item. Must not be <code>null</code>.
-        *
-        * @return The command input field handler. Must not be <code>null</code>.
-        *
-        * @since 4.1
-        */
-       protected TabCommandFieldHandler createTabCommandFieldHandler(TabFolderManager tabFolderManager, CTabItem item) {
-               return new TabCommandFieldHandler(tabFolderManager, item);
-       }
-
-       /**
-        * Dispose the command input field handler for the given tab item.
-        *
-        * @param item The tab item or <code>null</code>.
-        */
-       protected void disposeTabCommandFieldHandler(CTabItem item) {
-               // Null items or disposed items cannot be matched
-               if (item == null || item.isDisposed()) return;
-
-               TabCommandFieldHandler handler = commandFieldHandler.remove(item);
-               if (handler != null) handler.dispose();
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
-        */
-       @Override
-       public void addSelectionChangedListener(ISelectionChangedListener listener) {
-               if (listener != null && !selectionChangedListeners.contains(listener)) selectionChangedListeners.add(listener);
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
-        */
-       @Override
-       public void removeSelectionChangedListener(ISelectionChangedListener listener) {
-               if (listener != null) selectionChangedListeners.remove(listener);
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
-        */
-       @Override
-       public ISelection getSelection() {
-               CTabItem activeTabItem = getActiveTabItem();
-               return activeTabItem != null ? new StructuredSelection(activeTabItem) : new StructuredSelection();
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
-        */
-       @Override
-       public void setSelection(ISelection selection) {
-               if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
-                       // The first selection element which is a CTabItem will become the active item
-                       Iterator<?> iterator = ((IStructuredSelection)selection).iterator();
-                       while (iterator.hasNext()) {
-                               Object candidate = iterator.next();
-                               if (candidate instanceof CTabItem) { bringToTop((CTabItem)candidate); return; }
-                       }
-               }
-               // fire a changed event in any case
-               fireSelectionChanged(selection);
-       }
-
-       /**
-        * Fire the selection changed event to the registered listeners.
-        */
-       protected void fireSelectionChanged() {
-               updateStatusLine();
-               fireSelectionChanged(getSelection());
-       }
-
-       /**
-        * Fire the selection changed event with the terminal text!
-        * to the registered listeners.
-        * see also TerminalControlSelectionListener- mouseUp
-        *
-        * @since 4.1
-        */
-       protected void fireTerminalSelectionChanged() {
-               updateStatusLine();
-               CTabItem item = getActiveTabItem();
-               if (item != null && !item.isDisposed()) {
-                       ITerminalViewControl terminal = (ITerminalViewControl)item.getData();
-                       if (terminal != null && !terminal.isDisposed()) {
-                               fireSelectionChanged(new StructuredSelection(terminal.getSelection()));
-                       }
-               }
-       }
-
-       /**
-        * Fire the selection changed event to the registered listeners.
-        */
-       protected final void fireSelectionChanged(ISelection selection) {
-               // Create the selection changed event
-               SelectionChangedEvent event = new SelectionChangedEvent(TabFolderManager.this, selection);
-
-               // First, invoke the registered listeners and let them do their job
-               for (ISelectionChangedListener listener : selectionChangedListeners) {
-                       listener.selectionChanged(event);
-               }
-       }
-
-       /**
-        * Update the parent view status line.
-        */
-       public final void updateStatusLine() {
-               String message = null;
-               IStatusLineManager manager = parentView.getViewSite().getActionBars().getStatusLineManager();
-
-               CTabItem item = getActiveTabItem();
-               if (item != null && !item.isDisposed()) {
-                       ITerminalViewControl terminal = (ITerminalViewControl)item.getData();
-                       if (terminal != null && !terminal.isDisposed()) {
-                               StringBuilder buffer = new StringBuilder();
-
-                               buffer.append(state2msg(item, terminal.getState()));
-                               buffer.append(" - "); //$NON-NLS-1$
-
-                               String encoding = terminal.getEncoding();
-                               if (encoding == null || "ISO-8859-1".equals(encoding)) { //$NON-NLS-1$
-                                       encoding = "Default (ISO-8859-1)"; //$NON-NLS-1$
-                               }
-                               buffer.append(NLS.bind(Messages.TabFolderManager_encoding, encoding));
-
-                               message = buffer.toString();
-                       }
-               }
-
-               manager.setMessage(message);
-       }
-
-       /**
-        * Returns the string representation of the given terminal state.
-        *
-        * @param item The tab folder item. Must not be <code>null</code>.
-        * @param state The terminal state. Must not be <code>null</code>.
-        *
-        * @return The string representation.
-        */
-       @SuppressWarnings("unchecked")
+                // paste when the middle button is clicked
+                if (e.button == 2) {
+                    Clipboard clipboard = terminal.getClipboard();
+                    if (clipboard.isDisposed())
+                        return;
+                    int clipboardType = DND.SELECTION_CLIPBOARD;
+                    if (clipboard.getAvailableTypes(clipboardType).length == 0)
+                        // use normal clipboard if selection clipboard is not available
+                        clipboardType = DND.CLIPBOARD;
+                    String text = (String) clipboard.getContents(TextTransfer.getInstance(), clipboardType);
+                    if (text != null && text.length() > 0)
+                        terminal.pasteString(text);
+                }
+            }
+        });
+    }
+
+    /**
+     * Generate a unique title string based on the given proposal.
+     * @param proposal The proposal. Must not be <code>null</code>.
+     * @return The unique title string.
+     */
+    protected String makeUniqueTitle(String proposal, CTabFolder tabFolder) {
+        Assert.isNotNull(proposal);
+        Assert.isNotNull(tabFolder);
+
+        String title = proposal;
+        int index = 0;
+
+        // Loop all existing tab items and check the titles. We have to remember
+        // all found titles as modifying the proposal might in turn conflict again
+        // with the title of a tab already checked.
+        List<String> titles = new ArrayList<String>();
+        for (CTabItem item : tabFolder.getItems()) {
+            // Get the tab item title
+            titles.add(item.getText());
+        }
+        // Make the proposal unique be appending (<n>) against all known titles.
+        while (titles.contains(title))
+            title = proposal + " (" + ++index + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+
+        return title;
+    }
+
+    /**
+     * Setup the terminal console tab item listeners.
+     * @param item The tab item. Must not be <code>null</code>.
+     */
+    protected void setupTerminalTabListeners(final CTabItem item) {
+        Assert.isNotNull(item);
+
+        // Create and associate the disposal listener
+        DisposeListener disposeListener = doCreateTerminalTabDisposeListener(this);
+
+        // store the listener to make access easier e.g. needed in DnD
+        item.setData("disposeListener", disposeListener); //$NON-NLS-1$
+        item.addDisposeListener(disposeListener);
+    }
+
+    /**
+     * Creates a new terminal console tab terminal listener instance.
+     * @param tabFolderManager The tab folder manager. Must not be <code>null</code>.
+     * @param item The tab item. Must not be <code>null</code>.
+     * @return The terminal listener instance.
+     */
+    protected ITerminalListener doCreateTerminalTabTerminalListener(TabFolderManager tabFolderManager, CTabItem item) {
+        Assert.isNotNull(item);
+        return new TabTerminalListener(tabFolderManager, item);
+    }
+
+    /**
+     * Creates a new terminal console tab dispose listener instance.
+     * @param parent The parent terminal console tab folder manager. Must not be <code>null</code>.
+     * @return The dispose listener instance.
+     */
+    protected DisposeListener doCreateTerminalTabDisposeListener(TabFolderManager parent) {
+        Assert.isNotNull(parent);
+        return new TabDisposeListener(parent);
+    }
+
+    /**
+     * Returns the tab item image.
+     * @param connector The terminal connector. Must not be <code>null</code>.
+     * @param data The custom terminal data node or <code>null</code>.
+     * @return The tab item image or <code>null</code>.
+     */
+    protected Image getTabItemImage(ITerminalConnector connector, Object data) {
+        Assert.isNotNull(connector);
+        return UIPlugin.getImage(ImageConsts.VIEW_Terminals);
+    }
+
+    /**
+     * Lookup a tab item with the given title and the given terminal connector.
+     * <p>
+     * <b>Note:</b> The method will handle unified tab item titles itself.
+     * @param title The tab item title. Must not be <code>null</code>.
+     * @param connector The terminal connector. Must not be <code>null</code>.
+     * @param data The custom terminal data node or <code>null</code>.
+     * @return The corresponding tab item or <code>null</code>.
+     */
+    public CTabItem findTabItem(String title, ITerminalConnector connector, Object data) {
+        Assert.isNotNull(title);
+        Assert.isNotNull(connector);
+
+        // Get the tab folder
+        CTabFolder tabFolder = getTabFolder();
+        if (tabFolder == null)
+            return null;
+
+        // Loop all existing tab items and try to find a matching title
+        for (CTabItem item : tabFolder.getItems()) {
+            // Disposed items cannot be matched
+            if (item.isDisposed())
+                continue;
+            // Get the title from the current tab item
+            String itemTitle = item.getText();
+            // The terminal console state might be signaled to the user via the
+            // terminal console tab title. Filter out any prefix "<.*>\s*".
+            itemTitle = itemTitle.replaceFirst("^<.*>\\s*", ""); //$NON-NLS-1$ //$NON-NLS-2$
+            if (itemTitle.startsWith(title)) {
+                // The title string matches -> double check with the terminal connector
+                ITerminalViewControl terminal = (ITerminalViewControl) item.getData();
+                ITerminalConnector connector2 = terminal.getTerminalConnector();
+                // If the connector id and name matches -> check on the settings
+                if (connector.getId().equals(connector2.getId()) && connector.getName().equals(connector2.getName())) {
+                    if (!connector.isInitialized()) {
+                        // an uninitialized connector does not yield a sensible summary
+                        return item;
+                    }
+                    String summary = connector.getSettingsSummary();
+                    String summary2 = connector2.getSettingsSummary();
+                    // If we have matching settings -> we've found the matching item
+                    if (summary.equals(summary2))
+                        return item;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Make the given tab item the active tab and bring the tab to the top.
+     * @param item The tab item. Must not be <code>null</code>.
+     */
+    public void bringToTop(CTabItem item) {
+        Assert.isNotNull(item);
+
+        // Get the tab folder
+        CTabFolder tabFolder = getTabFolder();
+        if (tabFolder == null)
+            return;
+
+        // Set the given tab item as selection to the tab folder
+        tabFolder.setSelection(item);
+        // Fire selection changed event
+        fireSelectionChanged();
+    }
+
+    /**
+     * Returns the currently active tab.
+     * @return The active tab item or <code>null</code> if none.
+     */
+    public CTabItem getActiveTabItem() {
+        // Get the tab folder
+        CTabFolder tabFolder = getTabFolder();
+        if (tabFolder == null)
+            return null;
+
+        return tabFolder.getSelection();
+    }
+
+    /**
+     * Remove all terminated tab items.
+     */
+    public void removeTerminatedItems() {
+        // Get the tab folder
+        CTabFolder tabFolder = getTabFolder();
+        if (tabFolder == null)
+            return;
+
+        // Loop the items and check for terminated status
+        for (CTabItem item : tabFolder.getItems()) {
+            // Disposed items cannot be matched
+            if (item.isDisposed())
+                continue;
+            // Check if the item is terminated
+            if (isTerminatedTabItem(item)) {
+                // item is terminated -> dispose
+                item.dispose();
+            }
+        }
+    }
+
+    /**
+     * Checks if the given tab item represents a terminated console. Subclasses may overwrite this method to extend the definition of terminated.
+     * @param item The tab item or <code>null</code>.
+     * @return <code>True</code> if the tab item represents a terminated console, <code>false</code> otherwise.
+     */
+    protected boolean isTerminatedTabItem(CTabItem item) {
+        // Null items or disposed items cannot be matched
+        if (item == null || item.isDisposed())
+            return false;
+
+        // First, match the item title. If it contains "<terminated>", the item can be removed
+        String itemTitle = item.getText();
+        if (itemTitle != null && itemTitle.contains("<terminated>")) { //$NON-NLS-1$
+            return true;
+        }
+        // Second, check if the associated terminal control is closed
+        // The title string matches -> double check with the terminal connector
+        ITerminalViewControl terminal = (ITerminalViewControl) item.getData();
+        if (terminal != null && terminal.getState() == TerminalState.CLOSED) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns the command input field handler for the given tab item.
+     * @param item The tab item or <code>null</code>.
+     * @return The command input field handler or <code>null</code>.
+     */
+    public final TabCommandFieldHandler getTabCommandFieldHandler(CTabItem item) {
+        // Null items or disposed items cannot be matched
+        if (item == null || item.isDisposed())
+            return null;
+
+        TabCommandFieldHandler handler = commandFieldHandler.get(item);
+        if (handler == null) {
+            handler = createTabCommandFieldHandler(this, item);
+            Assert.isNotNull(handler);
+            commandFieldHandler.put(item, handler);
+        }
+        return handler;
+    }
+
+    /**
+     * Create the command input field handler for the given tab item.
+     * @param tabFolderManager The parent tab folder manager. Must not be <code>null</code>
+     * @param item The associated tab item. Must not be <code>null</code>.
+     * @return The command input field handler. Must not be <code>null</code>.
+     * @since 4.1
+     */
+    protected TabCommandFieldHandler createTabCommandFieldHandler(TabFolderManager tabFolderManager, CTabItem item) {
+        return new TabCommandFieldHandler(tabFolderManager, item);
+    }
+
+    /**
+     * Dispose the command input field handler for the given tab item.
+     * @param item The tab item or <code>null</code>.
+     */
+    protected void disposeTabCommandFieldHandler(CTabItem item) {
+        // Null items or disposed items cannot be matched
+        if (item == null || item.isDisposed())
+            return;
+
+        TabCommandFieldHandler handler = commandFieldHandler.remove(item);
+        if (handler != null)
+            handler.dispose();
+    }
+
+    /**
+     * Returns the SaveLog handler for the given tab item.
+     * @param item The tab item or <code>null</code>.
+     * @return The SaveLog handler or <code>null</code>.
+     */
+    public final ToggleSaveLogHandler getSaveLogHandler(CTabItem item) {
+        // Null items or disposed items cannot be matched
+        if (item == null || item.isDisposed())
+            return null;
+
+        ToggleSaveLogHandler handler = saveLogHandlerMap.get(item);
+        if (handler == null) {
+            handler = createSaveLogHandler(this, item);
+            Assert.isNotNull(handler);
+            saveLogHandlerMap.put(item, handler);
+        }
+        return handler;
+    }
+
+    /**
+     * Dispose the SaveLog handler for the given tab item.
+     * @param item The tab item or <code>null</code>.
+     */
+    protected void disposeSaveLogHandler(CTabItem item) {
+        // Null items or disposed items cannot be matched
+        if (item == null || item.isDisposed())
+            return;
+
+        ToggleSaveLogHandler handler = saveLogHandlerMap.remove(item);
+        if (handler != null)
+            handler.dispose();
+    }
+
+    /**
+     * Create the SaveLog handler for the given tab item.
+     * @param ToggleSaveLogHandler The parent tab folder manager. Must not be <code>null</code>
+     * @param item The associated tab item. Must not be <code>null</code>.
+     * @return The SaveLog handler. Must not be <code>null</code>.
+     */
+    protected ToggleSaveLogHandler createSaveLogHandler(TabFolderManager tabFolderManager, CTabItem item) {
+        return new ToggleSaveLogHandler(tabFolderManager, item);
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+     */
+    @Override
+    public void addSelectionChangedListener(ISelectionChangedListener listener) {
+        if (listener != null && !selectionChangedListeners.contains(listener))
+            selectionChangedListeners.add(listener);
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+     */
+    @Override
+    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+        if (listener != null)
+            selectionChangedListeners.remove(listener);
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
+     */
+    @Override
+    public ISelection getSelection() {
+        CTabItem activeTabItem = getActiveTabItem();
+        return activeTabItem != null ? new StructuredSelection(activeTabItem) : new StructuredSelection();
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
+     */
+    @Override
+    public void setSelection(ISelection selection) {
+        if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
+            // The first selection element which is a CTabItem will become the active item
+            Iterator<?> iterator = ((IStructuredSelection) selection).iterator();
+            while (iterator.hasNext()) {
+                Object candidate = iterator.next();
+                if (candidate instanceof CTabItem) {
+                    bringToTop((CTabItem) candidate);
+                    return;
+                }
+            }
+        }
+        // fire a changed event in any case
+        fireSelectionChanged(selection);
+    }
+
+    /**
+     * Fire the selection changed event to the registered listeners.
+     */
+    protected void fireSelectionChanged() {
+        updateStatusLine();
+        fireSelectionChanged(getSelection());
+    }
+
+    /**
+     * Fire the selection changed event with the terminal text! to the registered listeners. see also TerminalControlSelectionListener- mouseUp
+     * @since 4.1
+     */
+    protected void fireTerminalSelectionChanged() {
+        updateStatusLine();
+        CTabItem item = getActiveTabItem();
+        if (item != null && !item.isDisposed()) {
+            ITerminalViewControl terminal = (ITerminalViewControl) item.getData();
+            if (terminal != null && !terminal.isDisposed()) {
+                fireSelectionChanged(new StructuredSelection(terminal.getSelection()));
+            }
+        }
+    }
+
+    /**
+     * Fire the selection changed event to the registered listeners.
+     */
+    protected final void fireSelectionChanged(ISelection selection) {
+        // Create the selection changed event
+        SelectionChangedEvent event = new SelectionChangedEvent(TabFolderManager.this, selection);
+
+        // First, invoke the registered listeners and let them do their job
+        for (ISelectionChangedListener listener : selectionChangedListeners) {
+            listener.selectionChanged(event);
+        }
+    }
+
+    /**
+     * Update the parent view status line.
+     */
+    public final void updateStatusLine() {
+        String message = null;
+        IStatusLineManager manager = parentView.getViewSite().getActionBars().getStatusLineManager();
+
+        CTabItem item = getActiveTabItem();
+        if (item != null && !item.isDisposed()) {
+            ITerminalViewControl terminal = (ITerminalViewControl) item.getData();
+            if (terminal != null && !terminal.isDisposed()) {
+                StringBuilder buffer = new StringBuilder();
+
+                buffer.append(state2msg(item, terminal.getState()));
+                buffer.append(" - "); //$NON-NLS-1$
+
+                String encoding = terminal.getEncoding();
+                if (encoding == null || "ISO-8859-1".equals(encoding)) { //$NON-NLS-1$
+                    encoding = "Default (ISO-8859-1)"; //$NON-NLS-1$
+                }
+                buffer.append(NLS.bind(Messages.TabFolderManager_encoding, encoding));
+
+                message = buffer.toString();
+            }
+        }
+
+        manager.setMessage(message);
+    }
+
+    /**
+     * Returns the string representation of the given terminal state.
+     * @param item The tab folder item. Must not be <code>null</code>.
+     * @param state The terminal state. Must not be <code>null</code>.
+     * @return The string representation.
+     */
+    @SuppressWarnings("unchecked")
     protected String state2msg(CTabItem item, TerminalState state) {
-               Assert.isNotNull(item);
-               Assert.isNotNull(state);
-
-               // Determine the terminal properties of the tab folder
-               Map<String, Object> properties = (Map<String, Object>)item.getData("properties"); //$NON-NLS-1$
-
-               // Get he current terminal state as string
-               String stateStr = state.toString();
-               // Lookup a matching text representation of the state
-               String key = "TabFolderManager_state_" + stateStr.replaceAll("\\.", " ").trim().toLowerCase(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-               String stateMsg = null;
-               if (properties != null) stateMsg = properties.get(key) instanceof String ? (String) properties.get(key) : null;
-               if (stateMsg == null) stateMsg = Messages.getString(key);
-               if (stateMsg == null) stateMsg = stateStr;
-
-               return stateMsg;
-       }
+        Assert.isNotNull(item);
+        Assert.isNotNull(state);
+
+        // Determine the terminal properties of the tab folder
+        Map<String, Object> properties = (Map<String, Object>) item.getData("properties"); //$NON-NLS-1$
+
+        // Get he current terminal state as string
+        String stateStr = state.toString();
+        // Lookup a matching text representation of the state
+        String key = "TabFolderManager_state_" + stateStr.replaceAll("\\.", " ").trim().toLowerCase(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        String stateMsg = null;
+        if (properties != null)
+            stateMsg = properties.get(key) instanceof String ? (String) properties.get(key) : null;
+        if (stateMsg == null)
+            stateMsg = Messages.getString(key);
+        if (stateMsg == null)
+            stateMsg = stateStr;
+
+        return stateMsg;
+    }
 }
diff --git a/rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/tabs/ToggleSaveLogHandler.java b/rt-ide/org.eclipse.tm.terminal/plugins/org.eclipse.tm.terminal.view.ui/src/org/eclipse/tm/terminal/view/ui/tabs/ToggleSaveLogHandler.java
new file mode 100644 (file)
index 0000000..bd66efe
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * ToggleSaveLogHandler
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JaeMin Kim <jm.jemin.kim@samsung.com>
+ * HyeongSeok Heo <harry.heo@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ */
+package org.eclipse.tm.terminal.view.ui.tabs;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
+import org.eclipse.tm.internal.terminal.control.SaveLogOutputStream;
+import org.eclipse.ui.services.IDisposable;
+
+public class ToggleSaveLogHandler implements IDisposable, IAdaptable {
+
+    // Reference to the parent tab folder manager
+    private final TabFolderManager tabFolderManager;
+    // Reference to the associated tab
+    private final CTabItem item;
+
+    private SaveLogOutputStream saveLogOutputStream;
+    private String logFilePath;
+    private File fileBeforeClose;
+
+    public ToggleSaveLogHandler(TabFolderManager tabFolderManager, CTabItem item) {
+        super();
+        Assert.isNotNull(tabFolderManager);
+        this.tabFolderManager = tabFolderManager;
+        Assert.isNotNull(item);
+        this.item = item;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public Object getAdapter(Class adapter) {
+        if (TabFolderManager.class.equals(adapter)) {
+            return tabFolderManager;
+        }
+        if (CTabItem.class.equals(adapter)) {
+            return item;
+        }
+        return null;
+    }
+
+    /**
+     * Returns if or if not the associated tab item has the logOutputStream enabled.
+     * @return <code>True</code> if the logOutputStream is enabled, <code>false</code> otherwise.
+     */
+    public boolean hasLogOutputStream() {
+        return saveLogOutputStream != null;
+    }
+
+    public File getPath() {
+        if (saveLogOutputStream != null) {
+            return saveLogOutputStream.getPath();
+        }
+        return null;
+    }
+
+    @Override
+    public void dispose() {
+        // Close the stream (ignore exceptions on close)
+        try {
+            if (saveLogOutputStream != null) {
+                saveLogOutputStream.close();
+                saveLogOutputStream = null;
+            }
+        } catch (IOException e) {
+            // ignored on purpose
+        }
+    }
+
+    /**
+     * Set the logOutputStream on or off.
+     * @param on <code>True</code> for on, <code>false</code> for off.
+     */
+    public void setSaveLog(boolean on) {
+
+        if (saveLogOutputStream != null) {
+            try {
+                setBeforeCloseFile(saveLogOutputStream.getPath());
+                saveLogOutputStream.close();
+                saveLogOutputStream = null;
+            } catch (IOException e) {
+                // ignored on purpose
+            }
+        }
+
+        if (on) {
+            try {
+                saveLogOutputStream = new SaveLogOutputStream(new File(logFilePath), true);
+            } catch (FileNotFoundException e) {
+                // ignored on purpose
+            }
+        }
+
+        // Apply to the terminal control
+        Assert.isTrue(!item.isDisposed());
+        ITerminalViewControl terminal = (ITerminalViewControl) item.getData();
+        if (terminal != null)
+            terminal.setLogOutputStream(saveLogOutputStream);
+    }
+
+    public void setFileName(String logFilePath) {
+        this.logFilePath = logFilePath;
+    }
+
+    public void setBeforeCloseFile(File logFile) {
+        this.fileBeforeClose = logFile;
+    }
+
+    public File getBeforeCloseFile() {
+        return this.fileBeforeClose;
+    }
+}
index 14ba957..c490c55 100644 (file)
@@ -15,3 +15,4 @@ Require-Bundle: org.eclipse.ui,
  org.eclipse.osgi
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-ActivationPolicy: lazy
+Export-Package: org.tizen.rt.ide.terminal.view.ui.tabs
index 3d34c25..88bdb26 100644 (file)
@@ -24,9 +24,6 @@
  */
 package org.tizen.rt.ide.terminal.view.ui.tabs;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -41,12 +38,10 @@ import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
 import org.eclipse.tm.internal.terminal.control.SaveLogWithHistory;
 import org.eclipse.tm.internal.terminal.control.actions.AbstractTerminalAction;
-import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
 import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-import org.eclipse.tm.internal.terminal.provisional.api.provider.TerminalConnectorImpl;
-import org.eclipse.tm.terminal.connector.serial.connector.SerialConnector;
 import org.eclipse.tm.terminal.view.ui.interfaces.ITerminalsView;
 import org.eclipse.tm.terminal.view.ui.tabs.TabFolderManager;
+import org.eclipse.tm.terminal.view.ui.tabs.ToggleSaveLogHandler;
 import org.tizen.rt.ide.terminal.view.ui.activator.Activator;
 import org.tizen.rt.ide.terminal.view.ui.interfaces.ImageConsts;
 import org.tizen.rt.ide.terminal.view.ui.nls.Messages;
@@ -55,10 +50,6 @@ import org.tizen.rt.ide.util.ResourceUtil;
 public class ToggleSaveLogAction extends AbstractTerminalAction {
     private ITerminalsView view = null;
 
-    // Reference to the command input field
-    private SaveLogWithHistory saveLog;
-    private String resOflogPath;
-
     /**
      * Constructor.
      */
@@ -70,7 +61,8 @@ public class ToggleSaveLogAction extends AbstractTerminalAction {
                 Activator.getImageDescriptor(ImageConsts.ACTION_SaveLog_Hover),
                 Activator.getImageDescriptor(ImageConsts.ACTION_SaveLog_Enabled),
                 Activator.getImageDescriptor(ImageConsts.ACTION_SaveLog_Disabled), true);
-        setChecked(hasSaveLog());
+        ToggleSaveLogHandler handler = getSaveLogHandler();
+        setChecked(handler != null && handler.hasLogOutputStream());
     }
 
     /*
@@ -80,9 +72,32 @@ public class ToggleSaveLogAction extends AbstractTerminalAction {
      */
     @Override
     public void run() {
-        setSaveLog(!hasSaveLog());
+        ToggleSaveLogHandler handler = getSaveLogHandler();
+
+        if (handler != null) {
+            if (!handler.hasLogOutputStream()) {
+                handler.setFileName(openFileDialog());
+            }
+            handler.setSaveLog(!handler.hasLogOutputStream());
+        }
+        setChecked(handler != null && handler.hasLogOutputStream());
+    }
+
+    private String openFileDialog() {
+        TabFolderManager manager = (TabFolderManager) view.getAdapter(TabFolderManager.class);
+        CTabItem item = manager.getActiveTabItem();
+        Assert.isTrue(!item.isDisposed());
+
+        String DefaultPath = null;
+        IProject project = ResourceUtil.getCurrentProject();
+        if (project != null) {
+            DefaultPath = project.getLocation().toString();
+        } else {
+            // example) /home/user.home/ide/
+            DefaultPath = System.getProperty("user.dir");
+        }
 
-        setChecked(hasSaveLog());
+        return openFileDialog(DefaultPath, getLogFileName(item.getText()));
     }
 
     /*
@@ -94,65 +109,11 @@ public class ToggleSaveLogAction extends AbstractTerminalAction {
      */
     @Override
     public void updateAction(boolean aboutToShow) {
+        ToggleSaveLogHandler handler = getSaveLogHandler();
         ITerminalViewControl target = getTarget();
-        setEnabled(aboutToShow && target != null && target.getState() == TerminalState.CONNECTED);
-        setChecked(hasSaveLog());
-    }
-
-    /**
-     * Returns if or if not the associated tab item has the save log enabled.
-     * @return <code>True</code> if the save log is enabled, <code>false</code> otherwise.
-     */
-    public boolean hasSaveLog() {
-        return saveLog != null;
-    }
-
-    /**
-     * Set the save log field on or off.
-     * @param on <code>True</code> for on, <code>false</code> for off.
-     */
-    public void setSaveLog(boolean on) {
-
-        if (saveLog != null) {
-            saveLog = null;
-        }
-
-        TabFolderManager manager = (TabFolderManager) view.getAdapter(TabFolderManager.class);
-        CTabItem item = manager.getActiveTabItem();
-        Assert.isTrue(!item.isDisposed());
-
-        if (on) {
-            saveLog = new SaveLogWithHistory();
-
-            String DefaultPath = null;
-            IProject project = ResourceUtil.getCurrentProject();
-            if (project != null) {
-                DefaultPath = project.getLocation().toString();
-            } else {
-                DefaultPath = System.getProperty("user.dir");// ex.) /home/user.home/eclipse/
-            }
-
-            String logFileName = getLogFileName(item.getText());
-            resOflogPath = openFileDialog(DefaultPath, logFileName);
-        }
-
-        ITerminalViewControl terminal = (ITerminalViewControl) item.getData();
-        ITerminalConnector connector = terminal.getTerminalConnector();
-        TerminalConnectorImpl connectorImpl = connector.getAdapter(TerminalConnectorImpl.class);
-
-        if (connectorImpl instanceof SerialConnector) {
-            SerialConnector serialConnector = (SerialConnector) connectorImpl;
-
-            if (on) {
-                try {
-                    serialConnector.setCaptureStream(new FileOutputStream(new File(resOflogPath),true));
-                } catch (FileNotFoundException e) {
-                    e.printStackTrace();
-                }
-            } else {
-                serialConnector.setCaptureStream(null);
-            }
-        }
+        setEnabled(aboutToShow && handler != null
+                && target != null && target.getState() == TerminalState.CONNECTED);
+        setChecked(handler != null && handler.hasLogOutputStream());
     }
 
     private String openFileDialog(String defaultPath, String logFileName) {
@@ -186,4 +147,22 @@ public class ToggleSaveLogAction extends AbstractTerminalAction {
 
         return logFileName;
     }
+
+    /**
+     * Returns the saveLog handler for the active tab.
+     * @return The saveLog handler or <code>null</code>.
+     */
+    protected ToggleSaveLogHandler getSaveLogHandler() {
+        ToggleSaveLogHandler handler = null;
+        // Get the active tab item from the SaveLog manager
+        TabFolderManager manager = (TabFolderManager) view.getAdapter(TabFolderManager.class);
+        if (manager != null) {
+            // If we have the active tab item, we can get the active terminal control
+            CTabItem activeTabItem = manager.getActiveTabItem();
+            if (activeTabItem != null && !activeTabItem.isDisposed()) {
+                handler = manager.getSaveLogHandler(activeTabItem);
+            }
+        }
+        return handler;
+    }
 }