Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.terminal.control; singleton:=true
Bundle-Version: 1.1.200.qualifier
Bundle-Version: 1.1.300.qualifier
Bundle-Activator: org.eclipse.terminal.internal.control.impl.TerminalPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,19 @@ public interface ITerminalControlForText {
*/
void enableApplicationCursorKeys(boolean enable);

/**
* A program that asks for bracketed paste (CSI ?2004) wants pasted text marked
* as such, so that it can take it as text rather than as something typed.
*/
default void enableBracketedPaste(boolean enable) {
}

/**
* Shows or hides the cursor at the program's request (DEC mode 25).
*
* @param show whether the cursor is to be drawn
*/
default void showCursor(boolean show) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1264,38 +1264,64 @@ private void processAnsiCommand_X() {
}

private void processDecPrivateCommand_h() {
int param = getAnsiParameter(0);
// A program may set several modes at once: ncurses turns the mouse on with CSI ? 1006 ; 1000 h.
for (int i = 0; i <= nextAnsiParameter; i++) {
setDecPrivateMode(getAnsiParameter(i));
}
}

private void setDecPrivateMode(int param) {
switch (param) {
case 1:
// Enable Application Cursor Keys (DECCKM)
terminal.enableApplicationCursorKeys(true);
break;
case 25:
// Show cursor (DECTCEM).
terminal.showCursor(true);
break;
case 47:
case 1047:
case 1048:
case 1049:
// Use Alternate Screen Buffer (ignored).
break;
case 2004:
// Bracketed paste: pasted text is wrapped so a program can tell it from typing.
terminal.enableBracketedPaste(true);
break;
default:
Logger.log("Unsupported command parameter: CSI ?" + param + 'h'); //$NON-NLS-1$
break;
}
}

private void processDecPrivateCommand_l() {
int param = getAnsiParameter(0);
for (int i = 0; i <= nextAnsiParameter; i++) {
resetDecPrivateMode(getAnsiParameter(i));
}
}

private void resetDecPrivateMode(int param) {
switch (param) {
case 1:
// Enable Normal Cursor Keys (DECCKM)
terminal.enableApplicationCursorKeys(false);
break;
case 25:
// Hide cursor (DECTCEM).
terminal.showCursor(false);
break;
case 47:
case 1047:
case 1048:
case 1049:
// Use Normal Screen Buffer (ignored, but reset scroll region).
text.setScrollRegion(-1, -1);
break;
case 2004:
terminal.enableBracketedPaste(false);
break;
default:
Logger.log("Unsupported command parameter: CSI ?" + param + 'l'); //$NON-NLS-1$
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ public class VT100TerminalControl implements ITerminalControlForText, ITerminalC
*/
private final IPropertyChangeListener fPreferenceListener = this::updatePreferences;
private final IPropertyChangeListener fFontListener = this::updateFont;
private boolean fBracketedPaste;
private static final String PASTE_START = "\u001b[200~"; //$NON-NLS-1$
private static final String PASTE_END = "\u001b[201~"; //$NON-NLS-1$

/**
* Is protected by synchronize on this
Expand Down Expand Up @@ -308,7 +311,7 @@ public boolean pasteString(String strText) {
if (strText == null) {
return false;
}
sendString(strText);
sendString(fBracketedPaste ? bracketed(strText) : strText);
return true;
}

Expand Down Expand Up @@ -569,6 +572,16 @@ public Shell getShell() {
return getCtlText().getShell();
}

/**
* Marks text as pasted, so that a program takes the newlines in it as part of
* the text rather than as the user pressing return on each line. The end marker
* is taken out of the text itself, or the text could close the bracket early and
* the rest of it would arrive as if it had been typed.
*/
private static String bracketed(String text) {
return PASTE_START + text.replace(PASTE_END, "") + PASTE_END; //$NON-NLS-1$
}

protected void sendChar(char chKey, boolean altKeyPressed) {
try {
int byteToSend = chKey;
Expand Down Expand Up @@ -1288,6 +1301,11 @@ public void setState(TerminalState state) {
});
}

@Override
public void enableBracketedPaste(boolean enable) {
fBracketedPaste = enable;
}

/**
* @param runnable run in display thread
*/
Expand Down Expand Up @@ -1412,6 +1430,13 @@ public String getHoverSelection() {
return fCtlText.getHoverSelection();
}

@Override
public void showCursor(boolean show) {
if (fPollingTextCanvasModel != null) {
fPollingTextCanvasModel.setCursorHidden(!show);
}
}

@Override
public void updateTerminalDimensions() {
getTerminalText().adjustTerminalDimensions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ abstract public class AbstractTextCanvasModel implements ITextCanvasModel {
private boolean fShowCursor;
private long fCursorTime;
private boolean fCursorIsEnabled;
private boolean fCursorHidden;
private final ITerminalTextDataSnapshot fSnapshot;
private int fLines;

Expand Down Expand Up @@ -149,7 +150,12 @@ public int getCursorLine() {

@Override
public boolean isCursorOn() {
return fShowCursor && fCursorIsEnabled;
return fShowCursor && fCursorIsEnabled && !fCursorHidden;
}

/** A program hides the cursor while it draws, or for good, with DEC mode 25. */
public void setCursorHidden(boolean hidden) {
fCursorHidden = hidden;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ public OutputStream getOutputStream() {

}

private boolean cursorShown = true;
private boolean bracketedPaste;

@Override
public void showCursor(boolean show) {
cursorShown = show;
}

public boolean isCursorShown() {
return cursorShown;
}

@Override
public void enableBracketedPaste(boolean enable) {
bracketedPaste = enable;
}

public boolean isBracketedPaste() {
return bracketedPaste;
}

@Override
public void enableApplicationCursorKeys(boolean enable) {
throw new UnsupportedOperationException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.io.Reader;
Expand Down Expand Up @@ -375,4 +377,17 @@ public void testMalformedStringTerminator() {
() -> assertEquals(List.of("TITLE1", "TITLE2"), control.getAllTitles()));
}

@Test
public void testDecPrivateModes() {
// the cursor hidden and shown again by a program
run("\u001b[?25l");
assertFalse(control.isCursorShown());
run("\u001b[?25h");
assertTrue(control.isCursorShown());
// several modes in one sequence, as ncurses sends them: every one of them counts
run("\u001b[?2004;25l");
assertAll(() -> assertFalse(control.isCursorShown()), () -> assertFalse(control.isBracketedPaste()));
run("\u001b[?25;2004h");
assertAll(() -> assertTrue(control.isCursorShown()), () -> assertTrue(control.isBracketedPaste()));
}
}
Loading