diff --git a/terminal/plugins/org.eclipse.tm.terminal.control/META-INF/MANIFEST.MF b/terminal/plugins/org.eclipse.tm.terminal.control/META-INF/MANIFEST.MF index f208d8ece0e..e8f9acf6226 100644 --- a/terminal/plugins/org.eclipse.tm.terminal.control/META-INF/MANIFEST.MF +++ b/terminal/plugins/org.eclipse.tm.terminal.control/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.tm.terminal.control; singleton:=true -Bundle-Version: 5.5.300.qualifier +Bundle-Version: 5.5.301.qualifier Bundle-Activator: org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java b/terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java index af7eadd8254..e75a0f6d75d 100644 --- a/terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java +++ b/terminal/plugins/org.eclipse.tm.terminal.control/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java @@ -97,6 +97,12 @@ public class VT100Emulator implements ControlListener { */ private static final int ANSISTATE_EXPECTING_CHARSET_DESIGNATION = 5; + /** + * For cases where the OSC (OS Command) ends with a multi-byte ST (i.e. ESC \) + * we use this extra state. + */ + private static final int ANSISTATE_EXPECTING_OS_COMMAND_END = 6; + /** * This field holds the current state of the Finite TerminalState Automaton (FSA) * that recognizes ANSI escape sequences. @@ -428,16 +434,27 @@ public class VT100Emulator implements ControlListener { break; case ANSISTATE_EXPECTING_OS_COMMAND: - // A BEL (\u0007) character marks the end of the OSC sequence. + // A BEL (\u0007) or ESC \ ('\e\\') character marks the end of the OSC sequence. if (character == '\u0007') { ansiState = ANSISTATE_INITIAL; processAnsiOsCommand(); + } else if (character == '\u001b') { + ansiState = ANSISTATE_EXPECTING_OS_COMMAND_END; } else { ansiOsCommand.append(character); } break; + case ANSISTATE_EXPECTING_OS_COMMAND_END: + ansiState = ANSISTATE_INITIAL; + if (character == '\\') { + processAnsiOsCommand(); + } else { + Logger.log("Unsupported escape sequence: escape '" + ansiOsCommand + " \\e" + character + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + break; + case ANSISTATE_EXPECTING_DEC_PRIVATE_COMMAND: // Parameters can appear after the '[?' in an escape sequence, but they // are optional. diff --git a/terminal/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorTest.java b/terminal/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorTest.java index b32128bf928..66aa5941f0c 100644 --- a/terminal/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorTest.java +++ b/terminal/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/emulator/VT100EmulatorTest.java @@ -37,10 +37,18 @@ public class VT100EmulatorTest { private static final String CLEAR_ENTIRE_SCREEN = "\033[2J"; private static final String SCROLL_REVERSE = "\033M"; - private static String TITLE(String title) { + private static String TITLE_ST_BEL(String title) { return "\033]0;" + title + "\007"; } + private static String TITLE_ST_ESC_BACKSLASH(String title) { + return "\033]0;" + title + "\033\\"; + } + + private static String TITLE(String title) { + return TITLE_ST_BEL(title); + } + private static String SCROLL_REGION(int startRow, int endRow) { return "\033[" + startRow + ";" + endRow + "r"; } @@ -340,4 +348,31 @@ public class VT100EmulatorTest { assertAll(() -> assertCursorLocation(2, expected.get(2).length()), () -> assertTextEquals(expected)); } + @Test + public void testStringTerminator() { + run( // + TITLE_ST_BEL("TITLE1"), // + "HELLO1", // + TITLE_ST_ESC_BACKSLASH("TITLE2"), // + "HELLO2", // + TITLE_ST_BEL("TITLE3"), // + "HELLO3", // + TITLE_ST_ESC_BACKSLASH("TITLE4") // + ); + assertAll(() -> assertTextEquals("HELLO1HELLO2HELLO3"), + () -> assertEquals(List.of("TITLE1", "TITLE2", "TITLE3", "TITLE4"), control.getAllTitles())); + } + + @Test + public void testMalformedStringTerminator() { + run( // + TITLE_ST_ESC_BACKSLASH("TITLE1"), // + "\033]0;" + "TITLE1" + "\033X", // + TITLE_ST_ESC_BACKSLASH("TITLE2"), // + "HELLO" // + ); + assertAll(() -> assertTextEquals("HELLO"), + () -> assertEquals(List.of("TITLE1", "TITLE2"), control.getAllTitles())); + } + }