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.2.0.qualifier
Bundle-Activator: org.eclipse.terminal.internal.control.impl.TerminalPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down Expand Up @@ -30,5 +30,5 @@ Export-Package: org.eclipse.terminal.connector;version="1.0.100";
org.eclipse.terminal.internal.model;x-internal:=true,
org.eclipse.terminal.internal.preferences;x-internal:=true;x-friends:="org.eclipse.terminal.view.ui",
org.eclipse.terminal.internal.textcanvas;x-internal:=true,
org.eclipse.terminal.model;version="1.0.100";uses:="org.eclipse.swt.graphics"
org.eclipse.terminal.model;version="1.1.0";uses:="org.eclipse.swt.graphics"
Automatic-Module-Name: org.eclipse.terminal.control
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,10 @@ private void processAnsiCommand_m() {
style = style.setBold(true);
break;

case 2:
style = style.setDim(true);
break;

case 4:
style = style.setUnderline(true);
break;
Expand All @@ -931,7 +935,8 @@ private void processAnsiCommand_m() {

case 21:
case 22:
style = style.setBold(false);
// Normal intensity: undoes both of the two that change it.
style = style.setBold(false).setDim(false);
break;

case 24:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,70 @@ public Shell getShell() {
return getCtlText().getShell();
}

/**
* The sequences above are sent only when no modifier is held, so a program was
* never told about Ctrl+End and the rest of them. xterm spells a modified
* special key as the plain one carrying the modifier as a parameter, which is
* what this builds. Keys the switch already answered never reach here, so what
* works today keeps working.
*
* @return the sequence, or null when the key is not one that is spelled this way
*/
public static String modifiedSpecialKey(int keyCode, int modifierKeys) {
int modifier = 1 + ((modifierKeys & SWT.SHIFT) != 0 ? 1 : 0) + ((modifierKeys & SWT.ALT) != 0 ? 2 : 0)
+ ((modifierKeys & SWT.CTRL) != 0 ? 4 : 0);
if (modifier == 1) {
// Something held that xterm has no spelling for, the Mac's Cmd among them.
return null;
}
switch (keyCode) {
case 0x1000001: // Up arrow.
return "\u001b[1;" + modifier + 'A'; //$NON-NLS-1$
case 0x1000002: // Down arrow.
return "\u001b[1;" + modifier + 'B'; //$NON-NLS-1$
case 0x1000003: // Left arrow.
return "\u001b[1;" + modifier + 'D'; //$NON-NLS-1$
case 0x1000004: // Right arrow.
return "\u001b[1;" + modifier + 'C'; //$NON-NLS-1$
case 0x1000005: // PgUp key.
return "\u001b[5;" + modifier + '~'; //$NON-NLS-1$
case 0x1000006: // PgDn key.
return "\u001b[6;" + modifier + '~'; //$NON-NLS-1$
case 0x1000007: // Home key.
return "\u001b[1;" + modifier + 'H'; //$NON-NLS-1$
case 0x1000008: // End key.
return "\u001b[1;" + modifier + 'F'; //$NON-NLS-1$
case 0x1000009: // Insert.
return "\u001b[2;" + modifier + '~'; //$NON-NLS-1$
case 0x100000a: // F1, which xterm spells with a letter like the arrows.
return "\u001b[1;" + modifier + 'P'; //$NON-NLS-1$
case 0x100000b: // F2.
return "\u001b[1;" + modifier + 'Q'; //$NON-NLS-1$
case 0x100000c: // F3.
return "\u001b[1;" + modifier + 'R'; //$NON-NLS-1$
case 0x100000d: // F4.
return "\u001b[1;" + modifier + 'S'; //$NON-NLS-1$
case 0x100000e: // F5, and from here on a number, with 16 and 22 left out.
return "\u001b[15;" + modifier + '~'; //$NON-NLS-1$
case 0x100000f: // F6.
return "\u001b[17;" + modifier + '~'; //$NON-NLS-1$
case 0x1000010: // F7.
return "\u001b[18;" + modifier + '~'; //$NON-NLS-1$
case 0x1000011: // F8.
return "\u001b[19;" + modifier + '~'; //$NON-NLS-1$
case 0x1000012: // F9.
return "\u001b[20;" + modifier + '~'; //$NON-NLS-1$
case 0x1000013: // F10.
return "\u001b[21;" + modifier + '~'; //$NON-NLS-1$
case 0x1000014: // F11.
return "\u001b[23;" + modifier + '~'; //$NON-NLS-1$
case 0x1000015: // F12.
return "\u001b[24;" + modifier + '~'; //$NON-NLS-1$
default:
return null;
}
}

protected void sendChar(char chKey, boolean altKeyPressed) {
try {
int byteToSend = chKey;
Expand Down Expand Up @@ -1150,6 +1214,10 @@ public void keyPressed(KeyEvent event) {
break;
}

if (escSeq == null) {
escSeq = modifiedSpecialKey(event.keyCode, modifierKeys);
}

if (escSeq == null) {
// Any unmapped key should be handled locally by Eclipse
event.doit = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Color getForegroundColor(TerminalStyle style) {
foregroundRGB = style.getForegroundRGB();
}
if (foregroundRGB != null) {
return new Color(foregroundRGB);
return dimmed(style, new Color(foregroundRGB));
}

TerminalColor color;
Expand All @@ -101,7 +101,22 @@ public Color getForegroundColor(TerminalStyle style) {
}

color = color.convertColor(fInvertColors, style.isBold());
return getColor(color);
return dimmed(style, getColor(color));
}

/**
* SGR 2 asks for a fainter version of whatever colour is in force. Half way to
* the background keeps the text readable while setting it apart from the rest,
* and it works for any colour rather than only the sixteen named ones.
*/
private Color dimmed(TerminalStyle style, Color color) {
if (!style.isDim()) {
return color;
}
RGB rgb = color.getRGB();
RGB background = getBackgroundColor(style).getRGB();
return new Color((rgb.red + background.red) / 2, (rgb.green + background.green) / 2,
(rgb.blue + background.blue) / 2);
}

public Color getBackgroundColor(TerminalStyle style) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class TerminalStyle {
private final boolean fBlink;
private final boolean fUnderline;
private final boolean fReverse;
private final boolean fDim;
private final static Map<TerminalStyle, TerminalStyle> fgStyles = Collections
.synchronizedMap(new LinkedHashMap<TerminalStyle, TerminalStyle>() {
@Override
Expand All @@ -55,7 +56,8 @@ protected boolean removeEldestEntry(Map.Entry<TerminalStyle, TerminalStyle> elde
});

private TerminalStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor,
RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink, boolean underline, boolean reverse) {
RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink, boolean underline, boolean reverse,
boolean dim) {
Assert.isLegal(foregroundTerminalColor == null || foregroundRGB == null,
"Only one of ANSI or RGB colors can be specified as a foreground color"); //$NON-NLS-1$
Assert.isLegal(backgroundTerminalColor == null || backgroundRGB == null,
Expand All @@ -68,12 +70,24 @@ private TerminalStyle(TerminalColor foregroundTerminalColor, TerminalColor backg
fBlink = blink;
fUnderline = underline;
fReverse = reverse;
fDim = dim;
}

public static TerminalStyle getStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor,
RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink, boolean underline, boolean reverse) {
return getStyle(foregroundTerminalColor, backgroundTerminalColor, foregroundRGB, backgroundRGB, bold, blink,
underline, reverse, false);
}

/**
* @param dim SGR 2, drawn with the foreground moved toward the background
* @since 1.2
*/
public static TerminalStyle getStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor,
RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink, boolean underline, boolean reverse,
boolean dim) {
TerminalStyle style = new TerminalStyle(foregroundTerminalColor, backgroundTerminalColor, foregroundRGB,
backgroundRGB, bold, blink, underline, reverse);
backgroundRGB, bold, blink, underline, reverse, dim);
// If set had a computeIfAbsent we would use a set, instead just store 1-2-1 mapping
return fgStyles.computeIfAbsent(style, (s) -> style);
}
Expand All @@ -98,44 +112,44 @@ public static TerminalStyle getStyle(TerminalColor foregroundTerminalColor, Term

public TerminalStyle setForeground(TerminalColor foregroundTerminalColor) {
return getStyle(foregroundTerminalColor, fBackgroundTerminalColor, null, fBackgroundRGB, fBold, fBlink,
fUnderline, fReverse);
fUnderline, fReverse, fDim);
}

public TerminalStyle setBackground(TerminalColor backgroundTerminalColor) {
return getStyle(fForegroundTerminalColor, backgroundTerminalColor, fForegroundRGB, null, fBold, fBlink,
fUnderline, fReverse);
fUnderline, fReverse, fDim);
}

public TerminalStyle setForeground(RGB foregroundRGB) {
return getStyle(null, fBackgroundTerminalColor, foregroundRGB, fBackgroundRGB, fBold, fBlink, fUnderline,
fReverse);
fReverse, fDim);
}

public TerminalStyle setBackground(RGB backgroundRGB) {
return getStyle(fForegroundTerminalColor, null, fForegroundRGB, backgroundRGB, fBold, fBlink, fUnderline,
fReverse);
fReverse, fDim);
}

public TerminalStyle setForeground(TerminalStyle other) {
return getStyle(other.fForegroundTerminalColor, fBackgroundTerminalColor, other.fForegroundRGB, fBackgroundRGB,
fBold, fBlink, fUnderline, fReverse);
fBold, fBlink, fUnderline, fReverse, fDim);
}

public TerminalStyle setBackground(TerminalStyle other) {
return getStyle(fForegroundTerminalColor, other.fBackgroundTerminalColor, fForegroundRGB, other.fBackgroundRGB,
fBold, fBlink, fUnderline, fReverse);
fBold, fBlink, fUnderline, fReverse, fDim);
}

public TerminalStyle setForeground(int eightBitindexedColor) {
boolean isIndexTerminalColor = TerminalColor.isIndexedTerminalColor(eightBitindexedColor);
if (isIndexTerminalColor) {
TerminalColor foregroundTerminalColor = TerminalColor.getIndexedTerminalColor(eightBitindexedColor);
return getStyle(foregroundTerminalColor, fBackgroundTerminalColor, null, fBackgroundRGB, fBold, fBlink,
fUnderline, fReverse);
fUnderline, fReverse, fDim);
} else {
RGB foregroundRGB = TerminalColor.getIndexedRGBColor(eightBitindexedColor);
return getStyle(null, fBackgroundTerminalColor, foregroundRGB, fBackgroundRGB, fBold, fBlink, fUnderline,
fReverse);
fReverse, fDim);
}
}

Expand All @@ -144,32 +158,40 @@ public TerminalStyle setBackground(int eightBitindexedColor) {
if (isIndexTerminalColor) {
TerminalColor backgroundTerminalColor = TerminalColor.getIndexedTerminalColor(eightBitindexedColor);
return getStyle(fForegroundTerminalColor, backgroundTerminalColor, fForegroundRGB, null, fBold, fBlink,
fUnderline, fReverse);
fUnderline, fReverse, fDim);
} else {
RGB backgroundRGB = TerminalColor.getIndexedRGBColor(eightBitindexedColor);
return getStyle(fForegroundTerminalColor, null, fForegroundRGB, backgroundRGB, fBold, fBlink, fUnderline,
fReverse);
fReverse, fDim);
}
}

public TerminalStyle setBold(boolean bold) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, bold,
fBlink, fUnderline, fReverse);
fBlink, fUnderline, fReverse, fDim);
}

public TerminalStyle setBlink(boolean blink) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
blink, fUnderline, fReverse);
blink, fUnderline, fReverse, fDim);
}

public TerminalStyle setUnderline(boolean underline) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
fBlink, underline, fReverse);
fBlink, underline, fReverse, fDim);
}

public TerminalStyle setReverse(boolean reverse) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
fBlink, fUnderline, reverse);
fBlink, fUnderline, reverse, fDim);
}

/**
* @since 1.2
*/
public TerminalStyle setDim(boolean dim) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
fBlink, fUnderline, fReverse, dim);
}

public TerminalColor getForegroundTerminalColor() {
Expand Down Expand Up @@ -204,6 +226,14 @@ public boolean isUnderline() {
return fUnderline;
}

/**
* @return whether SGR 2 is in effect
* @since 1.2
*/
public boolean isDim() {
return fDim;
}

@Override
public int hashCode() {
final int prime = 31;
Expand All @@ -216,6 +246,7 @@ public int hashCode() {
result = prime * result + ((fForegroundRGB == null) ? 0 : fForegroundRGB.hashCode());
result = prime * result + (fReverse ? 1231 : 1237);
result = prime * result + (fUnderline ? 1231 : 1237);
result = prime * result + (fDim ? 1231 : 1237);
return result;
}

Expand Down Expand Up @@ -250,6 +281,9 @@ public boolean equals(Object obj) {
if (fForegroundTerminalColor != other.fForegroundTerminalColor) {
return false;
}
if (fDim != other.fDim) {
return false;
}
if (fForegroundRGB == null) {
if (other.fForegroundRGB != null) {
return false;
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,29 @@ public void testMalformedStringTerminator() {
() -> assertEquals(List.of("TITLE1", "TITLE2"), control.getAllTitles()));
}

@Test
public void testFaint() {
// SGR 2 makes the text faint; 22 takes both bold and faint off, as in xterm
run("\u001b[2mfaint\u001b[22m normal \u001b[1;2mboth\u001b[22mplain");
assertTrue(data.getStyle(0, 0).isDim());
assertFalse(data.getStyle(0, 0).isBold());
assertFalse(data.getStyle(0, 6).isDim());
assertTrue(data.getStyle(0, 13).isDim());
assertTrue(data.getStyle(0, 13).isBold());
assertFalse(data.getStyle(0, 17).isDim());
assertFalse(data.getStyle(0, 17).isBold());
}

@Test
public void testModifiedSpecialKeys() {
// xterm's spelling: the plain key with the modifier as a parameter, 2 shift, 3 alt, 5 control
assertEquals("\u001b[1;5A", VT100TerminalControl.modifiedSpecialKey(0x1000001, org.eclipse.swt.SWT.CTRL));
assertEquals("\u001b[1;2F", VT100TerminalControl.modifiedSpecialKey(0x1000008, org.eclipse.swt.SWT.SHIFT));
assertEquals("\u001b[5;3~", VT100TerminalControl.modifiedSpecialKey(0x1000005, org.eclipse.swt.SWT.ALT));
assertEquals("\u001b[1;6P", VT100TerminalControl.modifiedSpecialKey(0x100000a, org.eclipse.swt.SWT.CTRL | org.eclipse.swt.SWT.SHIFT));
assertEquals("\u001b[15;5~", VT100TerminalControl.modifiedSpecialKey(0x100000e, org.eclipse.swt.SWT.CTRL));
assertEquals("\u001b[24;2~", VT100TerminalControl.modifiedSpecialKey(0x1000015, org.eclipse.swt.SWT.SHIFT));
// no modifier held that xterm can spell: not this way
assertEquals(null, VT100TerminalControl.modifiedSpecialKey(0x1000001, 0));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,14 @@ private TerminalStyle getDefaultStyle() {
return TerminalStyle.getStyle(c1, c2, false, false, false, false);
}

@Test
public void testSetDim() {
TerminalStyle s1 = TerminalStyle.getStyle(c1, c2, true, false, true, false);
assertFalse(s1.isDim());
TerminalStyle s2 = s1.setDim(true);
assertNotSame(s1, s2);
assertTrue(s2.isDim());
assertTrue(s2.isBold()); // the rest is kept
assertSame(s1, s2.setDim(false));
}
}
Loading