From c934cb89c92f26f114213684bbd69d2a4344ee91 Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Mon, 26 Jan 2015 13:31:37 +0100 Subject: [PATCH] Bug 458398 - [terminal] Add support for application cursor keys mode Change-Id: Iad40fb34aae2bda478eecde1a6f13a63bc20f88b Signed-off-by: Anton Leherbauer --- .../terminal/test/ui/VT100DataSource.java | 6 +- .../control/impl/ITerminalControlForText.java | 9 ++- .../terminal/emulator/VT100Emulator.java | 65 +++++++++++++++++++ .../emulator/VT100TerminalControl.java | 25 ++++--- 4 files changed, 94 insertions(+), 11 deletions(-) diff --git a/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java b/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java index 69e66b8af87..5fc2628d108 100644 --- a/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java +++ b/plugins/org.eclipse.tm.terminal.test/src/org/eclipse/tm/internal/terminal/test/ui/VT100DataSource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2015 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 @@ -8,6 +8,7 @@ * Contributors: * Michael Scharf (Wind River) - initial API and implementation * Martin Oberhuber (Wind River) - [204796] Terminal should allow setting the encoding to use + * Anton Leherbauer (Wind River) - [458398] Add support for normal/application cursor keys mode *******************************************************************************/ package org.eclipse.tm.internal.terminal.test.ui; @@ -108,6 +109,9 @@ final class VT100DataSource implements IDataSource { public void setTerminalTitle(String title) { } + + public void enableApplicationCursorKeys(boolean enable) { + } }, reader); } public int step(ITerminalTextData terminal) { diff --git a/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java b/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java index 52e65c506b7..f15468023e7 100644 --- a/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java +++ b/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/control/impl/ITerminalControlForText.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2015 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 @@ -8,6 +8,7 @@ * Contributors: * Michael Scharf (Wind River) - initial API and implementation * Martin Oberhuber (Wind River) - fixed copyright headers and beautified + * Anton Leherbauer (Wind River) - [458398] Add support for normal/application cursor keys mode *******************************************************************************/ package org.eclipse.tm.internal.terminal.control.impl; @@ -31,4 +32,10 @@ public interface ITerminalControlForText { OutputStream getOutputStream(); + /** + * Enable/disable Application Cursor Keys mode (DECCKM) + * @param enable + */ + void enableApplicationCursorKeys(boolean enable); + } diff --git a/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java b/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java index 6a66ee51425..cc9e6cfa438 100644 --- a/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java +++ b/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100Emulator.java @@ -22,6 +22,7 @@ * Martin Oberhuber (Wind River) - [401480] Handle ESC[39;49m and ESC[G * Anton Leherbauer (Wind River) - [433751] Add option to enable VT100 line wrapping mode * Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert mode + * Anton Leherbauer (Wind River) - [458398] Add support for normal/application cursor keys mode *******************************************************************************/ package org.eclipse.tm.internal.terminal.emulator; @@ -70,6 +71,13 @@ public class VT100Emulator implements ControlListener { */ private static final int ANSISTATE_EXPECTING_OS_COMMAND = 3; + /** + * This is a character processing state: We've seen a '[?' after an escape + * character. Expecting a parameter character or a command character next. + */ + private static final int ANSISTATE_EXPECTING_DEC_PRIVATE_COMMAND = 4; + + /** * This field holds the current state of the Finite TerminalState Automaton (FSA) * that recognizes ANSI escape sequences. @@ -364,6 +372,11 @@ public class VT100Emulator implements ControlListener { break; case ANSISTATE_EXPECTING_PARAMETER_OR_COMMAND: + if (character == '?') { + ansiState = ANSISTATE_EXPECTING_DEC_PRIVATE_COMMAND; + break; + } + // Parameters can appear after the '[' in an escape sequence, but they // are optional. @@ -387,6 +400,19 @@ public class VT100Emulator implements ControlListener { } break; + case ANSISTATE_EXPECTING_DEC_PRIVATE_COMMAND: + // Parameters can appear after the '[?' in an escape sequence, but they + // are optional. + + if (character == '@' || (character >= 'A' && character <= 'Z') + || (character >= 'a' && character <= 'z')) { + ansiState = ANSISTATE_INITIAL; + processDecPrivateCommandCharacter(character); + } else { + processAnsiParameterCharacter(character); + } + break; + default: // This should never happen! If it does happen, it means there is a // bug in the FSA. For robustness, we return to the initial @@ -553,6 +579,31 @@ public class VT100Emulator implements ControlListener { } } + /** + * This method dispatches control to various processing methods based on the + * command character found in the most recently received DEC private mode escape + * sequence. This method only handles command characters that follow the + * control sequence CSI ? + */ + private void processDecPrivateCommandCharacter(char commandCharacter) { + switch (commandCharacter) { + case 'h': + // DEC Private Mode Set (DECSET) + processDecPrivateCommand_h(); + break; + + case 'l': + // DEC Private Mode Reset (DECRST) + processDecPrivateCommand_l(); + break; + + default: + Logger.log("Ignoring unsupported DEC private command character: '" + //$NON-NLS-1$ + commandCharacter + "'"); //$NON-NLS-1$ + break; + } + } + /** * This method makes room for N characters on the current line at the cursor * position. Text under the cursor moves right without wrapping at the end @@ -916,6 +967,20 @@ public class VT100Emulator implements ControlListener { text.deleteCharacters(getAnsiParameter(0)); } + private void processDecPrivateCommand_h() { + if (getAnsiParameter(0) == 1) { + // Enable Application Cursor Keys (DECCKM) + terminal.enableApplicationCursorKeys(true); + } + } + + private void processDecPrivateCommand_l() { + if (getAnsiParameter(0) == 1) { + // Enable Normal Cursor Keys (DECCKM) + terminal.enableApplicationCursorKeys(false); + } + } + /** * This method returns one of the numeric ANSI parameters received in the * most recent escape sequence. diff --git a/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java b/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java index 95e36b11ca1..a5d180b925a 100644 --- a/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java +++ b/plugins/org.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2014 Wind River Systems, Inc. and others. + * Copyright (c) 2003, 2015 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 @@ -37,6 +37,7 @@ * Martin Oberhuber (Wind River) - [434294] Add Mac bindings with COMMAND * Anton Leherbauer (Wind River) - [434749] UnhandledEventLoopException when copying to clipboard while the selection is empty * Martin Oberhuber (Wind River) - [436612] Restore Eclipse 3.4 compatibility by using Reflection + * Anton Leherbauer (Wind River) - [458398] Add support for normal/application cursor keys mode *******************************************************************************/ package org.eclipse.tm.internal.terminal.emulator; @@ -155,6 +156,8 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC private final EditActionAccelerators editActionAccelerators = new EditActionAccelerators(); + private boolean fApplicationCursorKeys; + /** * Listens to changes in the preferences */ @@ -958,22 +961,22 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC switch (event.keyCode) { case 0x1000001: // Up arrow. if (!anyModifierPressed) - escSeq = "\u001b[A"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOA" : "\u001b[A"; //$NON-NLS-1$ //$NON-NLS-2$ break; case 0x1000002: // Down arrow. if (!anyModifierPressed) - escSeq = "\u001b[B"; //$NON-NLS-1$ + 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 = "\u001b[D"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOD" : "\u001b[D"; //$NON-NLS-1$ //$NON-NLS-2$ } else if (onlyMacCmdKeyPressed) { // Cmd-Left is "Home" on the Mac - escSeq = "\u001b[H"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOH" : "\u001b[H"; //$NON-NLS-1$ //$NON-NLS-2$ } break; @@ -981,10 +984,10 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC if (onlyCtrlKeyPressed) { escSeq = "\u001b[1;5C"; //$NON-NLS-1$ } else if (!anyModifierPressed) { - escSeq = "\u001b[C"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOC" : "\u001b[C"; //$NON-NLS-1$ //$NON-NLS-2$ } else if (onlyMacCmdKeyPressed) { // Cmd-Right is "End" on the Mac - escSeq = "\u001b[F"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOF" : "\u001b[F"; //$NON-NLS-1$ //$NON-NLS-2$ } break; @@ -1000,12 +1003,12 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC case 0x1000007: // Home key. if (!anyModifierPressed) - escSeq = "\u001b[H"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOH" : "\u001b[H"; //$NON-NLS-1$ //$NON-NLS-2$ break; case 0x1000008: // End key. if (!anyModifierPressed) - escSeq = "\u001b[F"; //$NON-NLS-1$ + escSeq = fApplicationCursorKeys ? "\u001bOF" : "\u001b[F"; //$NON-NLS-1$ //$NON-NLS-2$ break; case 0x1000009: // Insert. @@ -1312,5 +1315,9 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC public boolean isVT100LineWrapping() { return getTerminalText().isVT100LineWrapping(); } + + public void enableApplicationCursorKeys(boolean enable) { + fApplicationCursorKeys = enable; + } }