From 986284fd1e932f628ee5d856e428fd712a7ce4c7 Mon Sep 17 00:00:00 2001 From: Michael Scharf Date: Mon, 9 Jun 2008 14:31:07 +0000 Subject: [PATCH] bug 204796: [terminal][api] Terminal should allow setting the encoding to use https://bugs.eclipse.org/bugs/show_bug.cgi?id=204796 --- .../connector/TerminalConnectorTest.java | 10 +++- .../terminal/test/ui/VT100DataSource.java | 29 +++++++---- .../terminal/emulator/VT100Emulator.java | 32 ++++++++---- .../emulator/VT100TerminalControl.java | 49 ++++++++++++++++-- .../provisional/api/ITerminalControl.java | 50 +++++++++++++++++-- 5 files changed, 139 insertions(+), 31 deletions(-) diff --git a/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/connector/TerminalConnectorTest.java b/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/connector/TerminalConnectorTest.java index bb0bb64de95..ffb0efe6700 100644 --- a/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/connector/TerminalConnectorTest.java +++ b/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/connector/TerminalConnectorTest.java @@ -7,7 +7,8 @@ * * Contributors: * Michael Scharf (Wind River) - initial API and implementation - * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl + * Martin Oberhuber (Wind River) - [225853][api] Provide more default functionality in TerminalConnectorImpl + * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use *******************************************************************************/ package org.eclipse.tm.internal.terminal.connector; @@ -41,6 +42,13 @@ public class TerminalConnectorTest extends TestCase { } public static class TerminalControlMock implements ITerminalControl { + public void setEncoding(String encoding) { + } + + public String getEncoding() { + return "ISO-8859-1"; //$NON-NLS-1$ + } + public void displayTextInTerminal(String text) { } diff --git a/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java b/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java index 96f63ed4339..69e66b8af87 100644 --- a/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java +++ b/terminal/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java @@ -1,12 +1,13 @@ /******************************************************************************* * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: * Michael Scharf (Wind River) - initial API and implementation + * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use *******************************************************************************/ package org.eclipse.tm.internal.terminal.test.ui; @@ -15,7 +16,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.Reader; +import java.io.UnsupportedEncodingException; import org.eclipse.tm.internal.terminal.control.impl.ITerminalControlForText; import org.eclipse.tm.internal.terminal.emulator.VT100Emulator; @@ -71,14 +75,20 @@ final class VT100DataSource implements IDataSource { fAvailable-=n; return n; } - + } void init(ITerminalTextData terminal) { + final Reader reader; + try { + reader = new InputStreamReader(new InfiniteFileInputStream(), "ISO-8859-1"); //$NON-NLS-1$ + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } fEmulator=new VT100Emulator(terminal,new ITerminalControlForText() { public void disconnectTerminal() { // TODO Auto-generated method stub - + } public OutputStream getOutputStream() { @@ -97,7 +107,8 @@ final class VT100DataSource implements IDataSource { } public void setTerminalTitle(String title) { - }},new InfiniteFileInputStream()); + } + }, reader); } public int step(ITerminalTextData terminal) { synchronized(terminal) { diff --git a/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java b/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java index f43bef9396f..566ad1873ef 100644 --- a/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java +++ b/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java @@ -118,13 +118,13 @@ public class VT100Emulator implements ControlListener { */ private int nextAnsiParameter = 0; - final Reader fReader; + Reader fReader; boolean fCrAfterNewLine; /** * The constructor. */ - public VT100Emulator(ITerminalTextData data,ITerminalControlForText terminal,InputStream input) { + public VT100Emulator(ITerminalTextData data, ITerminalControlForText terminal, Reader reader) { super(); Logger.log("entered"); //$NON-NLS-1$ @@ -134,15 +134,7 @@ public class VT100Emulator implements ControlListener { for (int i = 0; i < ansiParameters.length; ++i) { ansiParameters[i] = new StringBuffer(); } - Reader reader=null; - try { - // TODO convert byte to char using "ISO-8859-1" - reader=new InputStreamReader(input,"ISO-8859-1"); //$NON-NLS-1$ - } catch (UnsupportedEncodingException e) { - // should never happen! - e.printStackTrace(); - } - fReader=reader; + setInputStreamReader(reader); if(TerminalPlugin.isOptionEnabled("org.eclipse.tm.terminal/debug/log/VT100Backend")) //$NON-NLS-1$ text=new VT100BackendTraceDecorator(new VT100EmulatorBackend(data),System.out); else @@ -153,6 +145,24 @@ public class VT100Emulator implements ControlListener { text.setDefaultStyle(style); text.setStyle(style); } + + /** + * Set the reader that this Terminal gets its input from. + * + * The reader can be changed while the Terminal is running, but a change of + * the reader likely loses some characters which have not yet been fully + * read. Changing the reader can be done in order to change the selected + * Encoding, though. This is typically done when the Terminal is + * constructed, i.e. before it really starts operation; or, when the user + * manually selects a different encoding and thus doesn't care about losing + * old characters. + * + * @param reader the new Reader + */ + public void setInputStreamReader(Reader reader) { + fReader = reader; + } + public void setDimensions(int lines,int cols) { text.setDimensions(lines, cols); ITerminalConnector telnetConnection = getConnector(); diff --git a/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java b/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java index 87e0cd46733..1854c7742c7 100644 --- a/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java +++ b/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java @@ -21,10 +21,12 @@ * Ruslan Sychev (Xored Software) - [217675] NPE or SWTException when closing Terminal View while connection establishing * Michael Scharf (Wing River) - [196447] The optional terminal input line should be resizeable * Martin Oberhuber (Wind River) - [168197] Replace JFace MessagDialog by SWT MessageBox + * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use *******************************************************************************/ package org.eclipse.tm.internal.terminal.emulator; import java.io.IOException; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.SocketException; @@ -106,6 +108,9 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC private ITerminalConnector fConnector; private final ITerminalConnector[] fConnectors; PipedInputStream fInputStream; + private static final String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding(); + private String fEncoding = defaultEncoding; + private InputStreamReader fInputStreamReader; private ICommandInputField fCommandInputField; @@ -124,11 +129,39 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC fTerminalModel=TerminalTextDataFactory.makeTerminalTextData(); fTerminalModel.setMaxHeight(1000); fInputStream=new PipedInputStream(8*1024); - fTerminalText=new VT100Emulator(fTerminalModel,this,fInputStream); + fTerminalText = new VT100Emulator(fTerminalModel, this, null); + try { + // Use Default Encoding as start, until setEncoding() is called + setEncoding(null); + } catch (UnsupportedEncodingException e) { + // Should never happen + e.printStackTrace(); + // Fall back to local Platform Default Encoding + fEncoding = defaultEncoding; + fInputStreamReader = new InputStreamReader(fInputStream); + fTerminalText.setInputStreamReader(fInputStreamReader); + } setupTerminal(wndParent); } + public void setEncoding(String encoding) throws UnsupportedEncodingException { + if (encoding == null) { + // TODO better use a standard remote-to-local encoding? + encoding = "ISO-8859-1"; //$NON-NLS-1$ + // TODO or better use the local default encoding? + // encoding = defaultEncoding; + } + fInputStreamReader = new InputStreamReader(fInputStream, fEncoding); + // remember encoding if above didn't throw an exception + fEncoding = encoding; + fTerminalText.setInputStreamReader(fInputStreamReader); + } + + public String getEncoding() { + return fEncoding; + } + public ITerminalConnector[] getConnectors() { return fConnectors; } @@ -166,8 +199,13 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC return false; if (strText == null) return false; - for (int i = 0; i < strText.length(); i++) { - sendChar(strText.charAt(i), 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; } @@ -401,8 +439,9 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC // 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()); + getOutputStream().write(string.getBytes(fEncoding)); getOutputStream().flush(); } catch (SocketException socketException) { displayTextInTerminal(socketException.getMessage()); @@ -579,7 +618,7 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC } private void writeToTerminal(String text) { try { - getRemoteToTerminalOutputStream().write(text.getBytes("ISO-8859-1")); //$NON-NLS-1$ + getRemoteToTerminalOutputStream().write(text.getBytes(fEncoding)); } catch (UnsupportedEncodingException e) { // should never happen! e.printStackTrace(); diff --git a/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java b/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java index 73e33130988..fc78b8f6092 100644 --- a/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java +++ b/terminal/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/provisional/api/ITerminalControl.java @@ -4,14 +4,16 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Michael Scharf (Wind River) - initial API and implementation * Martin Oberhuber (Wind River) - fixed copyright headers and beautified + * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use *******************************************************************************/ package org.eclipse.tm.internal.terminal.provisional.api; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import org.eclipse.swt.widgets.Shell; @@ -24,7 +26,7 @@ import org.eclipse.swt.widgets.Shell; * with the Target Management * team. *

- * + * * @author Michael Scharf * @noimplement This interface is not intended to be implemented by clients. */ @@ -47,9 +49,47 @@ public interface ITerminalControl { Shell getShell(); /** - * Show a text in the terminal. If puts newlines at the beginning and the end. - * @param text - * TODO: Michael Scharf: Is this really needed? + * Set the encoding that the Terminal uses to decode bytes from the + * Terminal-to-remote-Stream into Unicode Characters used in Java; or, to + * encode Characters typed by the user into bytes sent over the wire to the + * remote. + * + * By default, the local Platform Default Encoding is used. Also note that + * the encoding must not be applied in case the terminal stream is processed + * by some data transfer protocol which requires binary data. + * + * Validity of the encoding set here is not checked. Since some encodings do + * not cover the entire range of Unicode characters, it can happen that a + * particular Unicode String typed in by the user can not be encoded into a + * byte Stream with the encoding specified. and UnsupportedEncodingException + * will be thrown in this case at the time the String is about to be + * processed. + * + * The concrete encoding to use can either be specified manually by a user, + * by means of a dialog, or a connector can try to obtain it automatically + * from the remote side e.g. by evaluating an environment variable such as + * LANG on UNIX systems. + * + * @since org.eclipse.tm.terminal 2.0 + */ + void setEncoding(String encoding) throws UnsupportedEncodingException; + + /** + * Return the current encoding. That's interesting when the previous + * setEncoding() call failed and the fallback default encoding should be + * queried, such that e.g. a combobox with encodings to choose can be + * properly initialized. + * + * @return the current Encoding of the Terminal. + * @since org.eclipse.tm.terminal 2.0 + */ + String getEncoding(); + + /** + * Show a text in the terminal. If puts newlines at the beginning and the + * end. + * + * @param text TODO: Michael Scharf: Is this really needed? */ void displayTextInTerminal(String text);