mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-08 21:47:59 -05:00
Merge remote-tracking branch 'origin/GP-6191_Dan_fixTerminal' into patch
This commit is contained in:
@@ -55,6 +55,9 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
|||||||
|
|
||||||
protected final CharsetDecoder decoder;
|
protected final CharsetDecoder decoder;
|
||||||
|
|
||||||
|
// For "repeat char"
|
||||||
|
protected byte lastChar;
|
||||||
|
|
||||||
// States for handling VT-style charsets
|
// States for handling VT-style charsets
|
||||||
protected final Map<VtCharset.G, VtCharset> vtCharsets = new HashMap<>();
|
protected final Map<VtCharset.G, VtCharset> vtCharsets = new HashMap<>();
|
||||||
protected VtCharset.G curVtCharsetG = VtCharset.G.G0;
|
protected VtCharset.G curVtCharsetG = VtCharset.G.G0;
|
||||||
@@ -265,9 +268,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
|||||||
return NumericUtilities.convertBytesToString(data, ":");
|
return NumericUtilities.convertBytesToString(data, ":");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void doHandleCharBytes() {
|
||||||
public void handleChar(byte b) throws Exception {
|
|
||||||
bb.put(b);
|
|
||||||
bb.flip();
|
bb.flip();
|
||||||
CoderResult result = decoder.decode(bb, cb, false);
|
CoderResult result = decoder.decode(bb, cb, false);
|
||||||
if (result.isError()) {
|
if (result.isError()) {
|
||||||
@@ -292,6 +293,13 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
|||||||
cb.clear();
|
cb.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleChar(byte b) throws Exception {
|
||||||
|
bb.put(b);
|
||||||
|
lastChar = b;
|
||||||
|
doHandleCharBytes();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleBell() {
|
public void handleBell() {
|
||||||
DockingWindowManager.beep();
|
DockingWindowManager.beep();
|
||||||
@@ -314,6 +322,28 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* It's unclear exactly what is repeated. Some documentation, including
|
||||||
|
* http://rheuh.free.fr/docpack/C/ansi/ansi.html says Repeat Character or Control. Here, I only
|
||||||
|
* handle characters. I tried repeating a Cursor Up control. I also tried repeating a new line.
|
||||||
|
* Neither did what I expected when tested against the reference. That said, those control also
|
||||||
|
* seemed to "forget" what the last character was. Nothing was repeated at all. I'll assume that
|
||||||
|
* is undefined behavior. I'll not worry about "forgetting," as I'll assume the character to
|
||||||
|
* repeat will always immediately precede this CSI.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleRepeatChar(int n) {
|
||||||
|
if (lastChar == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
bb.put(lastChar);
|
||||||
|
}
|
||||||
|
doHandleCharBytes();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleLineFeed() {
|
public void handleLineFeed() {
|
||||||
buffer.moveCursorDown(1, true);
|
buffer.moveCursorDown(1, true);
|
||||||
|
|||||||
@@ -956,6 +956,12 @@ public interface VtHandler {
|
|||||||
handleBackwardTab(n);
|
handleBackwardTab(n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 'b': { // Repeat last character
|
||||||
|
OfInt bits = parseCsiInts(csiParam);
|
||||||
|
int n = bits.hasNext() ? bits.nextInt() : 1;
|
||||||
|
handleRepeatChar(n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
case 'c': { // Send Device Attributes
|
case 'c': { // Send Device Attributes
|
||||||
Msg.trace(this, "TODO: Send Device Attributes");
|
Msg.trace(this, "TODO: Send Device Attributes");
|
||||||
return;
|
return;
|
||||||
@@ -1331,6 +1337,15 @@ public interface VtHandler {
|
|||||||
*/
|
*/
|
||||||
void handleBackwardTab(int n);
|
void handleBackwardTab(int n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the repeat char sequence: repeat the last character n more times.
|
||||||
|
* <p>
|
||||||
|
* If the terminal is not in wrap mode, truncate anything beyond the last column.
|
||||||
|
*
|
||||||
|
* @param n
|
||||||
|
*/
|
||||||
|
void handleRepeatChar(int n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the line feed control code (0x0a), usually just move the cursor down one.
|
* Handle the line feed control code (0x0a), usually just move the cursor down one.
|
||||||
*/
|
*/
|
||||||
@@ -1753,7 +1768,7 @@ public interface VtHandler {
|
|||||||
*
|
*
|
||||||
* @param n the number of lines to scroll
|
* @param n the number of lines to scroll
|
||||||
* @param intoScrollBack specifies whether the top line may flow into the scroll-back buffer
|
* @param intoScrollBack specifies whether the top line may flow into the scroll-back buffer
|
||||||
* @see #handleScrollViewportDown(int)
|
* @see #handleScrollViewportDown(int, boolean)
|
||||||
*/
|
*/
|
||||||
default void handleScrollLinesUp(int n, boolean intoScrollBack) {
|
default void handleScrollLinesUp(int n, boolean intoScrollBack) {
|
||||||
handleScrollViewportDown(n, intoScrollBack);
|
handleScrollViewportDown(n, intoScrollBack);
|
||||||
|
|||||||
@@ -139,6 +139,15 @@ public class VtParser {
|
|||||||
state = doProcess(state, buf);
|
state = doProcess(state, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void debugChar(char c) {
|
||||||
|
if (!Character.isISOControl(c)) {
|
||||||
|
System.err.print("%c".formatted(c));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.print("\\x%02x".formatted(c & 0xff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a given byte by delegating to the current state machine node
|
* Process a given byte by delegating to the current state machine node
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assume.assumeFalse;
|
import static org.junit.Assume.assumeFalse;
|
||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -33,6 +34,7 @@ import docking.widgets.fieldpanel.support.*;
|
|||||||
import ghidra.app.plugin.core.clipboard.ClipboardPlugin;
|
import ghidra.app.plugin.core.clipboard.ClipboardPlugin;
|
||||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
|
import ghidra.framework.Application;
|
||||||
import ghidra.framework.OperatingSystem;
|
import ghidra.framework.OperatingSystem;
|
||||||
import ghidra.pty.*;
|
import ghidra.pty.*;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
@@ -88,6 +90,41 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTermmines() throws Exception {
|
||||||
|
assumeFalse(SystemUtilities.isInTestingBatchMode());
|
||||||
|
assumeFalse(OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS);
|
||||||
|
|
||||||
|
terminalService = addPlugin(tool, TerminalPlugin.class);
|
||||||
|
clipboardService = addPlugin(tool, ClipboardPlugin.class);
|
||||||
|
|
||||||
|
env.showFrontEndTool();
|
||||||
|
|
||||||
|
PtyFactory factory = PtyFactory.local();
|
||||||
|
File termmines = Application.getModuleDataFile("TestResources", "termmines").getFile(false);
|
||||||
|
try (Pty pty = factory.openpty()) {
|
||||||
|
Map<String, String> env = new HashMap<>(System.getenv());
|
||||||
|
env.put("TERM", "xterm-256color");
|
||||||
|
PtySession session =
|
||||||
|
pty.getChild().session(new String[] { termmines.getAbsolutePath() }, env);
|
||||||
|
|
||||||
|
PtyParent parent = pty.getParent();
|
||||||
|
PtyChild child = pty.getChild();
|
||||||
|
try (Terminal term = terminalService.createWithStreams(Charset.forName("UTF-8"),
|
||||||
|
parent.getInputStream(), parent.getOutputStream())) {
|
||||||
|
term.addTerminalListener(new TerminalListener() {
|
||||||
|
@Override
|
||||||
|
public void resized(short cols, short rows) {
|
||||||
|
System.err.println("resized: " + cols + "x" + rows);
|
||||||
|
child.setWindowSize(cols, rows);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
session.waitExited();
|
||||||
|
pty.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
public void testCmd() throws Exception {
|
public void testCmd() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user