mirror of
https://gitlab.com/AutumnMeowMeow/jexer
synced 2024-09-19 11:50:19 -06:00
XTGETTCAP support
This commit is contained in:
parent
543000f0af
commit
287404c276
4 changed files with 147 additions and 28 deletions
|
@ -846,7 +846,9 @@ public class TTerminalWidget extends TScrollableWidget
|
|||
*/
|
||||
public void setDirty() {
|
||||
synchronized (dirtyQueue) {
|
||||
dirtyQueue.add("dirty");
|
||||
if (dirtyQueue.size() == 0) {
|
||||
dirtyQueue.add("dirty");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1508,10 +1510,14 @@ public class TTerminalWidget extends TScrollableWidget
|
|||
* Called by emulator when fresh data has come in.
|
||||
*/
|
||||
public void displayChanged() {
|
||||
setDirty();
|
||||
TApplication app = getApplication();
|
||||
if (app != null) {
|
||||
app.postEvent(new TMenuEvent(null, TMenu.MID_REPAINT));
|
||||
synchronized (dirtyQueue) {
|
||||
if (dirtyQueue.size() == 0) {
|
||||
dirtyQueue.add("dirty");
|
||||
TApplication app = getApplication();
|
||||
if (app != null) {
|
||||
app.postEvent(new TMenuEvent(null, TMenu.MID_REPAINT));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -314,10 +314,11 @@ public class SwingTerminal extends LogicalScreen
|
|||
private boolean mouse3 = false;
|
||||
|
||||
/**
|
||||
* If true, draw text glyphs underneath images on cells. This is
|
||||
* expensive.
|
||||
* If true, draw text glyphs underneath images on cells. This can be
|
||||
* expensive, but if the images are trimmed to minimize transparent
|
||||
* pixels (as ECMA48 and Bitmap do) then it isn't bad.
|
||||
*/
|
||||
private boolean imagesOverText = false;
|
||||
private boolean imagesOverText = true;
|
||||
|
||||
/**
|
||||
* If true, report mouse events per-pixel rather than per-text-cell.
|
||||
|
@ -689,10 +690,10 @@ public class SwingTerminal extends LogicalScreen
|
|||
setMouseStyle(System.getProperty("jexer.Swing.mouseStyle", "default"));
|
||||
|
||||
if (System.getProperty("jexer.Swing.imagesOverText",
|
||||
"false").equals("true")) {
|
||||
imagesOverText = true;
|
||||
} else {
|
||||
"true").equals("false")) {
|
||||
imagesOverText = false;
|
||||
} else {
|
||||
imagesOverText = true;
|
||||
}
|
||||
|
||||
// Set custom colors
|
||||
|
|
|
@ -629,14 +629,6 @@ public class Cell extends CellAttributes {
|
|||
*/
|
||||
@Override
|
||||
public void setTo(final Object rhs) {
|
||||
// Let this throw a ClassCastException
|
||||
CellAttributes thatAttr = (CellAttributes) rhs;
|
||||
this.image = null;
|
||||
this.imageHashCode = 0;
|
||||
this.backgroundHashCode = 0;
|
||||
this.width = Width.SINGLE;
|
||||
super.setTo(thatAttr);
|
||||
|
||||
if (rhs instanceof Cell) {
|
||||
Cell that = (Cell) rhs;
|
||||
this.ch = that.ch;
|
||||
|
@ -647,7 +639,15 @@ public class Cell extends CellAttributes {
|
|||
this.imageHashCode = that.imageHashCode;
|
||||
this.backgroundHashCode = that.backgroundHashCode;
|
||||
this.hasTransparentPixels = that.hasTransparentPixels;
|
||||
} else {
|
||||
this.image = null;
|
||||
this.imageHashCode = 0;
|
||||
this.backgroundHashCode = 0;
|
||||
this.width = Width.SINGLE;
|
||||
}
|
||||
// Let this throw a ClassCastException
|
||||
CellAttributes thatAttr = (CellAttributes) rhs;
|
||||
super.setTo(thatAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -150,6 +150,7 @@ public class ECMA48 implements Runnable {
|
|||
DCS_PASSTHROUGH,
|
||||
DCS_IGNORE,
|
||||
DCS_SIXEL,
|
||||
DCS_XTGETTCAP,
|
||||
SOSPMAPC_STRING,
|
||||
OSC_STRING,
|
||||
VT52_DIRECT_CURSOR_ADDRESS
|
||||
|
@ -241,6 +242,11 @@ public class ECMA48 implements Runnable {
|
|||
SGR_PIXELS
|
||||
}
|
||||
|
||||
/**
|
||||
* The version of the terminal to report in XTVERSION.
|
||||
*/
|
||||
private final String VERSION = "1.5.0";
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Variables --------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -508,6 +514,11 @@ public class ECMA48 implements Runnable {
|
|||
*/
|
||||
private HashMap<Integer, java.awt.Color> sixelPalette;
|
||||
|
||||
/**
|
||||
* XTGETTCAP collection buffer.
|
||||
*/
|
||||
private StringBuilder xtgettcapBuffer = new StringBuilder();
|
||||
|
||||
/**
|
||||
* The width of a character cell in pixels.
|
||||
*/
|
||||
|
@ -4886,9 +4897,9 @@ public class ECMA48 implements Runnable {
|
|||
if (i == 0) {
|
||||
// DCS > | {text} ST
|
||||
if (s8c1t == true) {
|
||||
writeRemote("\u0090>|jexer\u009c");
|
||||
writeRemote("\u0090>|jexer(" + VERSION + ")\u009c");
|
||||
} else {
|
||||
writeRemote("\033P>|jexer\033\\");
|
||||
writeRemote("\033P>|jexer(" + VERSION + ")\033\\");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5537,6 +5548,7 @@ public class ECMA48 implements Runnable {
|
|||
if ((type == DeviceType.XTERM)
|
||||
&& ((scanState == ScanState.OSC_STRING)
|
||||
|| (scanState == ScanState.DCS_SIXEL)
|
||||
|| (scanState == ScanState.DCS_XTGETTCAP)
|
||||
|| (scanState == ScanState.SOSPMAPC_STRING))
|
||||
) {
|
||||
// Xterm can pass ESCAPE to its OSC sequence.
|
||||
|
@ -7273,7 +7285,6 @@ public class ECMA48 implements Runnable {
|
|||
}
|
||||
if (ch == 0x5C) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == 0x1B)
|
||||
) {
|
||||
toGround();
|
||||
|
@ -7332,7 +7343,6 @@ public class ECMA48 implements Runnable {
|
|||
}
|
||||
if (ch == 0x5C) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == 0x1B)
|
||||
) {
|
||||
toGround();
|
||||
|
@ -7344,8 +7354,16 @@ public class ECMA48 implements Runnable {
|
|||
scanState = ScanState.DCS_IGNORE;
|
||||
}
|
||||
|
||||
// 0x40-7E goes to DCS_PASSTHROUGH
|
||||
if ((ch >= 0x40) && (ch <= 0x7E)) {
|
||||
if (ch == 0x71) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == '+')
|
||||
) {
|
||||
// DCS + q --> XTGETTCAP
|
||||
xtgettcapBuffer.setLength(0);
|
||||
scanState = ScanState.DCS_XTGETTCAP;
|
||||
}
|
||||
} else if ((ch >= 0x40) && (ch <= 0x7E)) {
|
||||
// 0x40-7E goes to DCS_PASSTHROUGH
|
||||
scanState = ScanState.DCS_PASSTHROUGH;
|
||||
}
|
||||
|
||||
|
@ -7365,7 +7383,6 @@ public class ECMA48 implements Runnable {
|
|||
}
|
||||
if (ch == 0x5C) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == 0x1B)
|
||||
) {
|
||||
toGround();
|
||||
|
@ -7428,7 +7445,6 @@ public class ECMA48 implements Runnable {
|
|||
}
|
||||
if (ch == 0x5C) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == 0x1B)
|
||||
) {
|
||||
toGround();
|
||||
|
@ -7482,7 +7498,6 @@ public class ECMA48 implements Runnable {
|
|||
}
|
||||
if (ch == 0x5C) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == 0x1B)
|
||||
) {
|
||||
parseSixel();
|
||||
|
@ -7503,6 +7518,41 @@ public class ECMA48 implements Runnable {
|
|||
// 7F --> ignore
|
||||
return;
|
||||
|
||||
case DCS_XTGETTCAP:
|
||||
// 0x9C goes to GROUND
|
||||
if (ch == 0x9C) {
|
||||
parseXtgettcap();
|
||||
toGround();
|
||||
return;
|
||||
}
|
||||
|
||||
// 0x1B 0x5C goes to GROUND
|
||||
if (ch == 0x1B) {
|
||||
collect((char) ch);
|
||||
return;
|
||||
}
|
||||
if (ch == 0x5C) {
|
||||
if ((collectBuffer.length() > 0)
|
||||
&& (collectBuffer.charAt(collectBuffer.length() - 1) == 0x1B)
|
||||
) {
|
||||
parseXtgettcap();
|
||||
toGround();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 00-17, 19, 1C-1F, 20-7E --> put
|
||||
if ((ch <= 0x17)
|
||||
|| (ch == 0x19)
|
||||
|| ((ch >= 0x1C) && (ch <= 0x1F))
|
||||
|| ((ch >= 0x20) && (ch <= 0x7E))
|
||||
) {
|
||||
xtgettcapBuffer.append((char) ch);
|
||||
}
|
||||
|
||||
// 7F --> ignore
|
||||
return;
|
||||
|
||||
case SOSPMAPC_STRING:
|
||||
// 00-17, 19, 1C-1F, 20-7F --> ignore
|
||||
|
||||
|
@ -7663,6 +7713,68 @@ public class ECMA48 implements Runnable {
|
|||
this.textHeight = textHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a XTGETTCAP request.
|
||||
*/
|
||||
private void parseXtgettcap() {
|
||||
// System.err.println("XTGETTCAP: '" + xtgettcapBuffer.toString() + "'");
|
||||
|
||||
String [] namesHex = xtgettcapBuffer.toString().split(";");
|
||||
StringBuilder name = new StringBuilder();
|
||||
for (int i = 0; i < namesHex.length; i++) {
|
||||
// System.err.println("XTGETTCAP: hex " + namesHex[i]);
|
||||
if ((namesHex[i].length() % 2) != 0) {
|
||||
// Incorrect format of name, bail out.
|
||||
return;
|
||||
}
|
||||
name.setLength(0);
|
||||
String nameHex = namesHex[i].toUpperCase();
|
||||
try {
|
||||
for (int j = 0; j < nameHex.length(); j += 2) {
|
||||
String ch = nameHex.substring(j, j + 2);
|
||||
name.append((char) Integer.parseInt(ch, 16));
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// Incorrect format of name, bail out.
|
||||
return;
|
||||
}
|
||||
// System.err.println("XTGETTCAP: '" + name + "'");
|
||||
|
||||
if (name.toString().equals("TN")) {
|
||||
writeXtgettcapResponse(name.toString(), "xterm-256color");
|
||||
}
|
||||
if (name.toString().equals("RGB")) {
|
||||
/*
|
||||
* See
|
||||
* https://gist.github.com/XVilka/8346728#true-color-detection
|
||||
*
|
||||
* We can pick either "truecolor" or "24bit".
|
||||
*/
|
||||
writeXtgettcapResponse(name.toString(), "truecolor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit the valid response to a XTGETTCAP query.
|
||||
*
|
||||
* @param name the name
|
||||
* @param value the value
|
||||
*/
|
||||
private void writeXtgettcapResponse(final String name, final String value) {
|
||||
StringBuilder response = new StringBuilder(16);
|
||||
response.append("\033P1+r");
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
response.append(Integer.toHexString(name.charAt(i)));
|
||||
}
|
||||
response.append("=");
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
response.append(Integer.toHexString(value.charAt(i)));
|
||||
}
|
||||
response.append("\033\\");
|
||||
writeRemote(response.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a sixel string into a bitmap image, and overlay that image onto
|
||||
* the text cells.
|
||||
|
|
Loading…
Reference in a new issue