1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-30 21:55:31 +02:00

Bug 540737: Add 8 and 24-bit color support to terminal

Change-Id: Iab3b648fb3bfa8f43f333371bd118e90a3a182f2
This commit is contained in:
Jonah Graham 2020-05-10 14:39:08 -04:00
parent d6818fbb03
commit 6d4f20edd6
12 changed files with 481 additions and 42 deletions

View file

@ -40,9 +40,11 @@ import static org.eclipse.tm.terminal.model.TerminalColor.YELLOW;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.tm.internal.terminal.control.impl.ITerminalControlForText;
import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
@ -859,6 +861,19 @@ public class VT100Emulator implements ControlListener {
while (parameterIndex < totalParameters && ansiParameters[parameterIndex].length() > 0) {
int ansiParameter = getAnsiParameter(parameterIndex);
if (ansiParameter == 1) {
String parameter = ansiParameters[parameterIndex].toString();
// Special case for ITU's T.416 foreground/background color specification
// which uses : to separate parameters instead of ;
if (parameter.startsWith("38:") || parameter.startsWith("48:")) { //$NON-NLS-1$ //$NON-NLS-2$
String[] split = parameter.split(":"); //$NON-NLS-1$
ProcessExtendedColorsReturn retval = processExtendedColors(split, style, true);
style = retval.style();
parameterIndex++;
continue;
}
}
switch (ansiParameter) {
case 0:
@ -974,6 +989,14 @@ public class VT100Emulator implements ControlListener {
style = style.setBackground(text.getDefaultStyle());
break;
case 38: // Foreground color defined by sequence
case 48: // Background color defined by sequence
CharSequence[] params = Arrays.copyOfRange(ansiParameters, parameterIndex, ansiParameters.length);
ProcessExtendedColorsReturn retval = processExtendedColors(params, style, false);
parameterIndex += retval.consumed() - 1;
style = retval.style();
break;
default:
Logger.log("Unsupported graphics rendition parameter: " + ansiParameter); //$NON-NLS-1$
break;
@ -984,6 +1007,110 @@ public class VT100Emulator implements ControlListener {
text.setStyle(style);
}
private interface ProcessExtendedColorsReturn {
/**
* @return the new style
*/
TerminalStyle style();
/**
* @return number of parameters consumed
*/
int consumed();
}
/**
*
* @param params array of parameters, starting with 38 or 48 being the command
* @param colorspace if a colorspace may be included (ITU T.416 mode)
*/
private ProcessExtendedColorsReturn processExtendedColors(CharSequence[] paramStrings, TerminalStyle style,
boolean colorspace) {
int params[] = new int[paramStrings.length];
for (int i = 0; i < params.length; i++) {
try {
int parseInt = Integer.parseInt(paramStrings[i].toString());
int inMagnitude = parseInt % 256;
int inRange = inMagnitude < 0 ? inMagnitude + 256 : inMagnitude;
params[i] = inRange;
} catch (NumberFormatException ex) {
params[i] = 0;
}
}
boolean foreground = params[0] == 38;
int consumed = 1;
if (params.length > 1) {
int colorDepth = params[1];
switch (colorDepth) {
case 2: // 24-bit RGB color
int r = 0, g = 0, b = 0;
if (colorspace) {
if (params.length < 6) {
Logger.log(
"Not enough parameters for 24-bit color depth, expected 5, one for color space and one for each of RGB"); //$NON-NLS-1$
}
} else {
if (params.length < 5) {
Logger.log("Not enough parameters for 24-bit color depth, expected 3, one for each of RGB"); //$NON-NLS-1$
}
}
int start = colorspace ? 3 : 2;
if (params.length > start + 0) {
r = params[start + 0];
}
if (params.length > start + 1) {
g = params[start + 1];
}
if (params.length > start + 2) {
b = params[start + 2];
}
RGB rgb = new RGB(r, g, b);
if (foreground) {
style = style.setForeground(rgb);
} else {
style = style.setBackground(rgb);
}
consumed = Math.min(6, params.length);
break;
case 5: // 8-bit color table lookup
int index = 0;
if (params.length < 3) {
Logger.log("Missing parameter for 8-bit color depth"); //$NON-NLS-1$
} else {
index = params[2];
}
if (foreground) {
style = style.setForeground(index);
} else {
style = style.setBackground(index);
}
consumed = Math.min(3, params.length);
break;
default:
Logger.log("Unsupported color depth " + colorDepth + " for: " + params[0]); //$NON-NLS-1$ //$NON-NLS-2$
}
} else {
Logger.log("Missing color depth for " + params[0]); //$NON-NLS-1$
}
TerminalStyle finalStyle = style;
int finalConsumed = consumed;
return new ProcessExtendedColorsReturn() {
@Override
public TerminalStyle style() {
return finalStyle;
}
@Override
public int consumed() {
return finalConsumed;
}
};
}
/**
* This method responds to an ANSI Device Status Report (DSR) command from
* the remote endpoint requesting the ready status or the cursor position.
@ -1096,7 +1223,7 @@ public class VT100Emulator implements ControlListener {
* most recent escape sequence.
*
* @return The <i>parameterIndex</i>th numeric ANSI parameter or -1 if the
* index is out of range.
* index is out of range or 1 if parse failed (1 is also a legitimate value)
*/
private int getAnsiParameter(int parameterIndex) {
if (parameterIndex < 0 || parameterIndex >= ansiParameters.length) {
@ -1109,6 +1236,7 @@ public class VT100Emulator implements ControlListener {
if (parameter.length() == 0)
return 1;
// return 1 on failed parseInt
int parameterValue = 1;
// Don't trust the remote endpoint to send well formed numeric

View file

@ -74,6 +74,16 @@ public class StyleMap {
public RGB getForegrondRGB(TerminalStyle style) {
style = defaultIfNull(style);
RGB foregroundRGB;
if (style.isReverse()) {
foregroundRGB = style.getBackgroundRGB();
} else {
foregroundRGB = style.getForegroundRGB();
}
if (foregroundRGB != null) {
return foregroundRGB;
}
TerminalColor color;
if (style.isReverse()) {
color = style.getBackgroundTerminalColor();
@ -91,6 +101,16 @@ public class StyleMap {
public RGB getBackgroundRGB(TerminalStyle style) {
style = defaultIfNull(style);
RGB backgroundRGB;
if (style.isReverse()) {
backgroundRGB = style.getForegroundRGB();
} else {
backgroundRGB = style.getBackgroundRGB();
}
if (backgroundRGB != null) {
return backgroundRGB;
}
TerminalColor color;
if (style.isReverse()) {
color = style.getForegroundTerminalColor();

View file

@ -20,6 +20,15 @@ import org.eclipse.swt.widgets.Display;
* the colors with well known names defined by the ANSI Escape Sequences, plus other colors needed
* to render a display (such as Background color).
*
* Rather than name all the colors when using ANSI 8-bit indexed colors, the indexed colors
* can be accessed via the {@link #getIndexedRGBColor(int)} or {@link #getIndexedRGBColor(int)}
* (use {@link #isIndexedTerminalColor(int)} to determine which one is appropriate.
*
* The {@link TerminalStyle} supports any arbitrary color by using {@link RGB} defined colors.
* This class provides the connection between the names exposed to the user in preferences
* and their use in the terminal, along with how colors change when other attributes (such as
* bright and invertColors) are applied to them.
*
* @since 5.0
*/
public enum TerminalColor {
@ -158,11 +167,37 @@ public enum TerminalColor {
}
/**
* FOR TEST ONLY.
* Query for whether the 8-bit color index will return a named color, in which case
* {@link #getIndexedTerminalColor(int)} must be called to get the named color. Use
* {@link #convertColor(boolean, boolean)} if this method returns false.
*
* @noreference This enum method is not intended to be referenced by clients.
* @param index 8-bit index.
* @return true for named colors, false for RGB colors
*/
public static TerminalColor getForTest(int c) {
return TerminalColor.values()[c % TerminalColor.values().length];
public static boolean isIndexedTerminalColor(int index) {
Assert.isLegal(index >= 0 && index < 256, "Invalid 8-bit table index out of range 0-255"); //$NON-NLS-1$
return index < table8bitIndexedTerminalColors.length && index >= 0;
}
/**
* Return the named color for the given 8-bit index.
*
* @param index 8-bit index in 0-15 range.
* @return named color
*/
public static TerminalColor getIndexedTerminalColor(int index) {
Assert.isLegal(isIndexedTerminalColor(index), "Invalid table index used for ANSI Color"); //$NON-NLS-1$
return table8bitIndexedTerminalColors[index];
}
/**
* Return the RGB color for the given 8-bit index.
*
* @param index 8-bit index in 16-255 range.
* @return RGB color
*/
public static RGB getIndexedRGBColor(int index) {
Assert.isLegal(index >= 16 && index < 256, "Invalid table index used for RGB Color"); //$NON-NLS-1$
return table8bitIndexedRGB[index - 16];
}
}

View file

@ -14,6 +14,8 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.tm.internal.terminal.control.impl.TerminalPlugin;
import org.eclipse.tm.internal.terminal.provisional.api.Logger;
@ -29,6 +31,8 @@ import org.eclipse.tm.internal.terminal.provisional.api.Logger;
public class TerminalStyle {
private final TerminalColor fForegroundTerminalColor;
private final TerminalColor fBackgroundTerminalColor;
private final RGB fForegroundRGB;
private final RGB fBackgroundRGB;
private final boolean fBold;
private final boolean fBlink;
private final boolean fUnderline;
@ -50,10 +54,16 @@ public class TerminalStyle {
}
});
private TerminalStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor, boolean bold,
boolean blink, boolean underline, boolean reverse) {
private TerminalStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor,
RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink, boolean underline, boolean reverse) {
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,
"Only one of ANSI or RGB colors can be specified as a background color"); //$NON-NLS-1$
fForegroundTerminalColor = foregroundTerminalColor;
fBackgroundTerminalColor = backgroundTerminalColor;
fForegroundRGB = foregroundRGB;
fBackgroundRGB = backgroundRGB;
fBold = bold;
fBlink = blink;
fUnderline = underline;
@ -61,51 +71,105 @@ public class TerminalStyle {
}
public static TerminalStyle getStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor,
boolean bold, boolean blink, boolean underline, boolean reverse) {
TerminalStyle style = new TerminalStyle(foregroundTerminalColor, backgroundTerminalColor, bold, blink,
underline, reverse);
RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink, boolean underline, boolean reverse) {
TerminalStyle style = new TerminalStyle(foregroundTerminalColor, backgroundTerminalColor, foregroundRGB,
backgroundRGB, bold, blink, underline, reverse);
// If set had a computeIfAbsent we would use a set, instead just store 1-2-1 mapping
return fgStyles.computeIfAbsent(style, (s) -> style);
}
public static TerminalStyle getStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor,
boolean bold, boolean blink, boolean underline, boolean reverse) {
return getStyle(foregroundTerminalColor, backgroundTerminalColor, null, null, bold, blink, underline, reverse);
}
public static TerminalStyle getStyle(RGB foregroundRGB, RGB backgroundRGB, boolean bold, boolean blink,
boolean underline, boolean reverse) {
return getStyle(null, null, foregroundRGB, backgroundRGB, bold, blink, underline, reverse);
}
public static TerminalStyle getDefaultStyle() {
return getStyle(TerminalColor.FOREGROUND, TerminalColor.BACKGROUND);
}
public static TerminalStyle getStyle(TerminalColor foregroundTerminalColor, TerminalColor backgroundTerminalColor) {
return getStyle(foregroundTerminalColor, backgroundTerminalColor, false, false, false, false);
return getStyle(foregroundTerminalColor, backgroundTerminalColor, null, null, false, false, false, false);
}
public TerminalStyle setForeground(TerminalColor foregroundTerminalColor) {
return getStyle(foregroundTerminalColor, fBackgroundTerminalColor, fBold, fBlink, fUnderline, fReverse);
return getStyle(foregroundTerminalColor, fBackgroundTerminalColor, null, fBackgroundRGB, fBold, fBlink,
fUnderline, fReverse);
}
public TerminalStyle setBackground(TerminalColor backgroundTerminalColor) {
return getStyle(fForegroundTerminalColor, backgroundTerminalColor, fBold, fBlink, fUnderline, fReverse);
return getStyle(fForegroundTerminalColor, backgroundTerminalColor, fForegroundRGB, null, fBold, fBlink,
fUnderline, fReverse);
}
public TerminalStyle setForeground(RGB foregroundRGB) {
return getStyle(null, fBackgroundTerminalColor, foregroundRGB, fBackgroundRGB, fBold, fBlink, fUnderline,
fReverse);
}
public TerminalStyle setBackground(RGB backgroundRGB) {
return getStyle(fForegroundTerminalColor, null, fForegroundRGB, backgroundRGB, fBold, fBlink, fUnderline,
fReverse);
}
public TerminalStyle setForeground(TerminalStyle other) {
return getStyle(other.fForegroundTerminalColor, fBackgroundTerminalColor, fBold, fBlink, fUnderline, fReverse);
return getStyle(other.fForegroundTerminalColor, fBackgroundTerminalColor, other.fForegroundRGB, fBackgroundRGB,
fBold, fBlink, fUnderline, fReverse);
}
public TerminalStyle setBackground(TerminalStyle other) {
return getStyle(fForegroundTerminalColor, other.fBackgroundTerminalColor, fBold, fBlink, fUnderline, fReverse);
return getStyle(fForegroundTerminalColor, other.fBackgroundTerminalColor, fForegroundRGB, other.fBackgroundRGB,
fBold, fBlink, fUnderline, fReverse);
}
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);
} else {
RGB foregroundRGB = TerminalColor.getIndexedRGBColor(eightBitindexedColor);
return getStyle(null, fBackgroundTerminalColor, foregroundRGB, fBackgroundRGB, fBold, fBlink, fUnderline,
fReverse);
}
}
public TerminalStyle setBackground(int eightBitindexedColor) {
boolean isIndexTerminalColor = TerminalColor.isIndexedTerminalColor(eightBitindexedColor);
if (isIndexTerminalColor) {
TerminalColor backgroundTerminalColor = TerminalColor.getIndexedTerminalColor(eightBitindexedColor);
return getStyle(fForegroundTerminalColor, backgroundTerminalColor, fForegroundRGB, null, fBold, fBlink,
fUnderline, fReverse);
} else {
RGB backgroundRGB = TerminalColor.getIndexedRGBColor(eightBitindexedColor);
return getStyle(fForegroundTerminalColor, null, fForegroundRGB, backgroundRGB, fBold, fBlink, fUnderline,
fReverse);
}
}
public TerminalStyle setBold(boolean bold) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, bold, fBlink, fUnderline, fReverse);
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, bold,
fBlink, fUnderline, fReverse);
}
public TerminalStyle setBlink(boolean blink) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fBold, blink, fUnderline, fReverse);
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
blink, fUnderline, fReverse);
}
public TerminalStyle setUnderline(boolean underline) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fBold, fBlink, underline, fReverse);
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
fBlink, underline, fReverse);
}
public TerminalStyle setReverse(boolean reverse) {
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fBold, fBlink, fUnderline, reverse);
return getStyle(fForegroundTerminalColor, fBackgroundTerminalColor, fForegroundRGB, fBackgroundRGB, fBold,
fBlink, fUnderline, reverse);
}
public TerminalColor getForegroundTerminalColor() {
@ -116,6 +180,14 @@ public class TerminalStyle {
return fBackgroundTerminalColor;
}
public RGB getForegroundRGB() {
return fForegroundRGB;
}
public RGB getBackgroundRGB() {
return fBackgroundRGB;
}
public boolean isBlink() {
return fBlink;
}
@ -137,9 +209,11 @@ public class TerminalStyle {
final int prime = 31;
int result = 1;
result = prime * result + ((fBackgroundTerminalColor == null) ? 0 : fBackgroundTerminalColor.hashCode());
result = prime * result + ((fBackgroundRGB == null) ? 0 : fBackgroundRGB.hashCode());
result = prime * result + (fBlink ? 1231 : 1237);
result = prime * result + (fBold ? 1231 : 1237);
result = prime * result + ((fForegroundTerminalColor == null) ? 0 : fForegroundTerminalColor.hashCode());
result = prime * result + ((fForegroundRGB == null) ? 0 : fForegroundRGB.hashCode());
result = prime * result + (fReverse ? 1231 : 1237);
result = prime * result + (fUnderline ? 1231 : 1237);
return result;
@ -156,12 +230,22 @@ public class TerminalStyle {
TerminalStyle other = (TerminalStyle) obj;
if (fBackgroundTerminalColor != other.fBackgroundTerminalColor)
return false;
if (fBackgroundRGB == null) {
if (other.fBackgroundRGB != null)
return false;
} else if (!fBackgroundRGB.equals(other.fBackgroundRGB))
return false;
if (fBlink != other.fBlink)
return false;
if (fBold != other.fBold)
return false;
if (fForegroundTerminalColor != other.fForegroundTerminalColor)
return false;
if (fForegroundRGB == null) {
if (other.fForegroundRGB != null)
return false;
} else if (!fForegroundRGB.equals(other.fForegroundRGB))
return false;
if (fReverse != other.fReverse)
return false;
if (fUnderline != other.fUnderline)
@ -173,9 +257,17 @@ public class TerminalStyle {
public String toString() {
StringBuffer result = new StringBuffer();
result.append("Style(foreground="); //$NON-NLS-1$
result.append(fForegroundTerminalColor);
if (fForegroundTerminalColor != null) {
result.append(fForegroundTerminalColor);
} else {
result.append(fForegroundRGB);
}
result.append(", background="); //$NON-NLS-1$
result.append(fBackgroundTerminalColor);
if (fForegroundTerminalColor != null) {
result.append(fBackgroundTerminalColor);
} else {
result.append(fBackgroundRGB);
}
if (fBlink)
result.append(", blink"); //$NON-NLS-1$
if (fBold)

View file

@ -14,7 +14,6 @@ package org.eclipse.tm.internal.terminal.model;
import org.eclipse.tm.terminal.model.ITerminalTextData;
import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
import org.eclipse.tm.terminal.model.LineSegment;
import org.eclipse.tm.terminal.model.TerminalColor;
import org.eclipse.tm.terminal.model.TerminalStyle;
import junit.framework.TestCase;
@ -338,13 +337,13 @@ abstract public class AbstractITerminalTextDataTest extends TestCase {
for (int line = 0; line < term.getHeight(); line++) {
for (int column = 0; column < term.getWidth(); column++) {
char c = (char) ('a' + column + line);
term.setChar(line, column, c, style.setForeground(TerminalColor.getForTest(c)));
term.setChar(line, column, c, style.setForeground(c));
}
}
for (int line = 0; line < term.getHeight(); line++) {
for (int column = 0; column < term.getWidth(); column++) {
char c = (char) ('a' + column + line);
assertSame(style.setForeground(TerminalColor.getForTest(c)), term.getStyle(line, column));
assertSame(style.setForeground(c), term.getStyle(line, column));
}
}

View file

@ -13,7 +13,6 @@ package org.eclipse.tm.internal.terminal.model;
import org.eclipse.tm.terminal.model.ITerminalTextData;
import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
import org.eclipse.tm.terminal.model.TerminalColor;
import org.eclipse.tm.terminal.model.TerminalStyle;
import junit.framework.TestCase;
@ -322,7 +321,7 @@ public class TerminalTextDataSnapshotTest extends TestCase {
for (int line = 0; line < term.getHeight(); line++) {
for (int column = 0; column < term.getWidth(); column++) {
char c = (char) ('a' + column + line);
term.setChar(line, column, c, style.setForeground(TerminalColor.getForTest(c)));
term.setChar(line, column, c, style.setForeground(c));
}
}
ITerminalTextDataSnapshot snapshot = term.makeSnapshot();
@ -331,7 +330,7 @@ public class TerminalTextDataSnapshotTest extends TestCase {
for (int line = 0; line < term.getHeight(); line++) {
for (int column = 0; column < term.getWidth(); column++) {
char c = (char) ('a' + column + line);
assertSame(style.setForeground(TerminalColor.getForTest(c)), snapshot.getStyle(line, column));
assertSame(style.setForeground(c), snapshot.getStyle(line, column));
}
}

View file

@ -17,7 +17,6 @@ import java.util.ArrayList;
import org.eclipse.tm.terminal.model.ITerminalTextData;
import org.eclipse.tm.terminal.model.LineSegment;
import org.eclipse.tm.terminal.model.TerminalColor;
import org.eclipse.tm.terminal.model.TerminalStyle;
public class TerminalTextDataWindowTest extends AbstractITerminalTextDataTest {
@ -214,7 +213,7 @@ public class TerminalTextDataWindowTest extends AbstractITerminalTextDataTest {
for (int line = 0; line < term.getHeight(); line++) {
for (int column = 0; column < term.getWidth(); column++) {
char c = (char) ('a' + column + line);
term.setChar(line, column, c, style.setForeground(TerminalColor.getForTest(c)));
term.setChar(line, column, c, style.setForeground(c));
}
}
for (int line = 0; line < term.getHeight(); line++) {
@ -222,7 +221,7 @@ public class TerminalTextDataWindowTest extends AbstractITerminalTextDataTest {
char c = (char) ('a' + column + line);
TerminalStyle s = null;
if (line >= fOffset && line < fOffset + fSize)
s = style.setForeground(TerminalColor.getForTest(c));
s = style.setForeground(c);
assertSame(s, term.getStyle(line, column));
}
}

View file

@ -15,7 +15,6 @@ package org.eclipse.tm.internal.terminal.model;
import org.eclipse.tm.terminal.model.ITerminalTextData;
import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
import org.eclipse.tm.terminal.model.TerminalColor;
import org.eclipse.tm.terminal.model.TerminalStyle;
public class TerminalTextTestHelper {
@ -66,7 +65,7 @@ public class TerminalTextTestHelper {
term.setDimensions(s.length(), 1);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
term.setChar(i, 0, c, style.setForeground(TerminalColor.getForTest(c)));
term.setChar(i, 0, c, style.setForeground(c));
}
}
@ -105,7 +104,7 @@ public class TerminalTextTestHelper {
yy++;
xx = column;
} else {
term.setChar(yy, xx, c, style.setForeground(TerminalColor.getForTest(c)));
term.setChar(yy, xx, c, style.setForeground(c));
xx++;
}
}

View file

@ -97,6 +97,8 @@ public class TerminalTextUITest {
addDataReader(composite, reader);
reader = new DataReader("Fast", fTerminalModel, new FastDataSource(), status);
addDataReader(composite, reader);
reader = new DataReader("Colors", fTerminalModel, new VT100DataSource(), status);
addDataReader(composite, reader);
reader = new DataReader("Random", fTerminalModel, new RandomDataSource(), status);
addDataReader(composite, reader);
for (int i = 0; i < args.length; i++) {

View file

@ -14,6 +14,7 @@
*******************************************************************************/
package org.eclipse.tm.internal.terminal.test.ui;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -40,18 +41,111 @@ final class VT100DataSource implements IDataSource {
volatile int fAvailable;
volatile int fRead;
private final String fFile;
private final String fANSIEscapeColors;
VT100DataSource(String file) {
fFile = file;
fANSIEscapeColors = null;
}
VT100DataSource() {
fFile = null;
StringBuffer input = new StringBuffer();
input.append(" 8-bit ");
for (int i = 0; i < 255; i++) {
input.append("\033[38:5:");
input.append(i);
input.append("m");
input.append(String.format(" %3s ", i));
input.append("\033[0m");
if ((i + 1) % 6 == 4) {
input.append("\n");
}
}
input.append("\n");
input.append(" 8-bit ");
for (int i = 0; i < 255; i++) {
input.append("\033[48:5:");
input.append(i);
input.append("m");
input.append(String.format(" %3s ", i));
input.append("\033[0m");
if ((i + 1) % 6 == 4) {
input.append("\n");
}
}
input.append("\n");
input.append("\n");
input.append(" 24-bit (RGB incremented by 15)");
int count = 0;
for (int r = 0; r < 255; r += 15) {
for (int g = 0; g < 255; g += 15) {
count = 0;
for (int b = 0; b < 255; b += 15) {
if (count++ % 5 == 0) {
input.append("\n");
}
input.append("\033[38:2:3:");
input.append(r);
input.append(":");
input.append(g);
input.append(":");
input.append(b);
input.append(":");
input.append("m");
input.append(String.format(" (%02x%02x%02x) ", r, g, b));
input.append("\033[0m");
}
}
}
input.append("\n");
input.append(" 24-bit (RGB incremented by 15)");
count = 0;
for (int r = 0; r < 255; r += 15) {
for (int g = 0; g < 255; g += 15) {
count = 0;
for (int b = 0; b < 255; b += 15) {
if (count++ % 5 == 0) {
input.append("\n");
}
input.append("\033[48:2:3:");
input.append(r);
input.append(":");
input.append(g);
input.append(":");
input.append(b);
input.append(":");
input.append("m");
input.append(String.format(" (%02x%02x%02x) ", r, g, b));
input.append("\033[0m");
}
}
}
input.append("\n");
fANSIEscapeColors = input.toString();
}
class InfiniteFileInputStream extends InputStream {
public InfiniteFileInputStream() {
try {
fInputStream = new FileInputStream(fFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
startInputStream();
}
private void startInputStream() {
if (fFile == null) {
fInputStream = new ByteArrayInputStream(fANSIEscapeColors.getBytes(StandardCharsets.ISO_8859_1));
} else {
try {
fInputStream = new FileInputStream(fFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@ -80,7 +174,7 @@ final class VT100DataSource implements IDataSource {
int n = fInputStream.read(b, off, len);
if (n <= 0) {
fInputStream.close();
fInputStream = new FileInputStream(fFile);
startInputStream();
n = fInputStream.read(b, off, len);
}
fAvailable -= n;

View file

@ -13,9 +13,9 @@ package org.eclipse.tm.terminal.model;
import junit.framework.TestCase;
public class StyleTest extends TestCase {
final TerminalColor c1 = TerminalColor.getForTest(1);
final TerminalColor c2 = TerminalColor.getForTest(2);
final TerminalColor c3 = TerminalColor.getForTest(3);
final TerminalColor c1 = TerminalColor.getIndexedTerminalColor(1);
final TerminalColor c2 = TerminalColor.getIndexedTerminalColor(2);
final TerminalColor c3 = TerminalColor.getIndexedTerminalColor(3);
public void testGetStyle() {
TerminalStyle s1 = TerminalStyle.getStyle(c1, c2, true, false, true, false);

View file

@ -17,6 +17,7 @@ import static org.eclipse.tm.terminal.model.TerminalColor.WHITE;
import static org.eclipse.tm.terminal.model.TerminalColor.YELLOW;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import org.eclipse.swt.widgets.Display;
import org.junit.AfterClass;
@ -79,4 +80,75 @@ public class TerminalColorUITest {
assertEquals(WHITE.convertColor(false, true), BLACK.convertColor(true, true));
assertNotEquals(WHITE.convertColor(false, true), BLACK.convertColor(false, true));
}
@Test
public void testIndexesResolveToStandardColors() {
// check explicit colors
assertEquals(TerminalColor.BLACK.convertColor(false, false),
TerminalColor.getIndexedTerminalColor(0).convertColor(false, false));
assertEquals(TerminalColor.RED.convertColor(false, false),
TerminalColor.getIndexedTerminalColor(1).convertColor(false, false));
// Now check all colors
for (int i = 0; i < 8; i++) {
assertEquals(TerminalColor.values()[i].convertColor(false, false),
TerminalColor.getIndexedTerminalColor(i).convertColor(false, false));
}
}
@Test
public void testIndexesResolveToBrightColors() {
// check explicit colors
assertEquals(TerminalColor.BLACK.convertColor(false, true),
TerminalColor.getIndexedTerminalColor(8).convertColor(false, false));
assertEquals(TerminalColor.RED.convertColor(false, true),
TerminalColor.getIndexedTerminalColor(9).convertColor(false, false));
// Now check all colors
for (int i = 0; i < 8; i++) {
assertEquals(TerminalColor.values()[i].convertColor(false, true),
TerminalColor.getIndexedTerminalColor(i + 8).convertColor(false, false));
}
}
@Test
public void testIndexesInRange() {
for (int i = 0; i < 16; i++) {
assertNotNull(TerminalColor.getIndexedTerminalColor(i));
}
for (int i = 16; i < 256; i++) {
assertNotNull(TerminalColor.getIndexedRGBColor(i));
}
}
@Test(expected = IllegalArgumentException.class)
public void testIndexesOutOfRange_m1TerminalColor() {
assertNotNull(TerminalColor.getIndexedTerminalColor(-1));
}
@Test(expected = IllegalArgumentException.class)
public void testIndexesOutOfRange_m1RGBColor() {
assertNotNull(TerminalColor.getIndexedRGBColor(-1));
}
@Test(expected = IllegalArgumentException.class)
public void testIndexesOutOfRange_16() {
assertNotNull(TerminalColor.getIndexedTerminalColor(16));
}
@Test(expected = IllegalArgumentException.class)
public void testIndexesOutOfRange_15() {
assertNotNull(TerminalColor.getIndexedRGBColor(15));
}
@Test(expected = IllegalArgumentException.class)
public void testIndexesOutOfRange_256TerminalColor() {
assertNotNull(TerminalColor.getIndexedTerminalColor(256));
}
@Test(expected = IllegalArgumentException.class)
public void testIndexesOutOfRange_256RGBColor() {
assertNotNull(TerminalColor.getIndexedRGBColor(256));
}
}