#91 DECSDM support in terminal widget

This commit is contained in:
Autumn Lamonte 2022-01-19 06:37:33 -06:00
parent 8953b42c71
commit b3f91a768c
4 changed files with 77 additions and 26 deletions

View file

@ -3405,13 +3405,16 @@ public class ECMA48Terminal extends LogicalScreen
}
// If the final image would be larger than 1000 pixels wide, break it
// up into smaller images. Or if we are using the HQ encoder and
// will have more than some multiple of the palette size in total
// pixels.
// up into smaller images, but at least 8 cells wide. Or if we are
// using the HQ encoder and will have more than some multiple of the
// palette size in total pixels.
int maxChunkLength = 1000;
if (sixelEncoder instanceof HQSixelEncoder) {
maxChunkLength = Math.min(maxChunkLength,
sixelEncoder.getPaletteSize() * 10 / getTextHeight());
if ((sixelEncoder instanceof HQSixelEncoder)
&& (sixelEncoder.getPaletteSize() > 8)
) {
maxChunkLength = Math.max(8 * getTextWidth(),
Math.min(maxChunkLength,
sixelEncoder.getPaletteSize() * 10 / getTextHeight()));
/*
System.err.printf("maxChunkLength: %d cache used size %d\n",
maxChunkLength, sixelCache.size());

View file

@ -305,14 +305,16 @@ public class LogicalScreen implements Screen {
public final boolean isDirty() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if (!logical[x][y].equals(physical[x][y])) {
return true;
}
if (logical[x][y].isBlink()) {
// Blinking screens are always dirty. There is
// opportunity for a Netscape blink tag joke here...
return true;
}
synchronized (this) {
if (!logical[x][y].equals(physical[x][y])) {
return true;
}
}
}
}
@ -429,8 +431,10 @@ public class LogicalScreen implements Screen {
// If this happens to be the cursor position, make the position
// dirty.
if ((cursorX == X) && (cursorY == Y)) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
synchronized (this) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
}
}
}
}
@ -488,8 +492,10 @@ public class LogicalScreen implements Screen {
// If this happens to be the cursor position, make the position
// dirty.
if ((cursorX == X) && (cursorY == Y)) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
synchronized (this) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
}
}
}
}
@ -535,8 +541,10 @@ public class LogicalScreen implements Screen {
// If this happens to be the cursor position, make the position
// dirty.
if ((cursorX == X) && (cursorY == Y)) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
synchronized (this) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
}
}
}
}
@ -573,8 +581,10 @@ public class LogicalScreen implements Screen {
// If this happens to be the cursor position, make the position
// dirty.
if ((cursorX == X) && (cursorY == Y)) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
synchronized (this) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
}
}
}
}
@ -922,8 +932,10 @@ public class LogicalScreen implements Screen {
&& (cursorX <= width - 1)
) {
// Make the current cursor position dirty
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
synchronized (this) {
physical[cursorX][cursorY].unset();
unsetImageRow(cursorY);
}
}
cursorVisible = visible;
@ -1023,7 +1035,7 @@ public class LogicalScreen implements Screen {
/**
* Clear the physical screen.
*/
public final void clearPhysical() {
public synchronized final void clearPhysical() {
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
physical[col][row].unset();

View file

@ -692,8 +692,14 @@ public class Cell extends CellAttributes {
return false;
}
assert (first != null);
assert (first.image != null);
assert (first.image.getWidth() == second.image.getWidth());
assert (first.image.getHeight() == second.image.getHeight());
int [] firstRgbArray = first.image.getRGB(0, 0, width, height,
null, 0, width);
assert (second != null);
assert (second.image != null);
int [] secondRgbArray = second.image.getRGB(0, 0, width, height,
null, 0, width);

View file

@ -519,6 +519,11 @@ public class ECMA48 implements Runnable {
*/
private HashMap<Integer, java.awt.Color> sixelPalette;
/**
* Sixel scrolling option.
*/
private boolean sixelScrolling = true;
/**
* XTGETTCAP collection buffer.
*/
@ -3632,11 +3637,24 @@ public class ECMA48 implements Runnable {
if (type == DeviceType.XTERM) {
if (decPrivateModeFlag == true) {
if (value == true) {
// Enable sixel scrolling (default).
// Not supported
// Set DECSDM: Disable sixel scrolling.
/*
* This was actually recorded incorrectly in the
* DEC VT330/340 programmer's guide
* (https://vt100.net/docs/vt3xx-gp/chapter14.html).
*
* On real hardware, setting 80 DISABLES
* scrolling. Much thanks to James Holderness
* for finding this and sharing it with several
* terminals:
*
* https://github.com/hackerb9/lsix/issues/41
*/
sixelScrolling = false;
} else {
// Disable sixel scrolling.
// Not supported
// Reset DECSDM: Enable sixel scrolling (default).
sixelScrolling = true;
}
}
}
@ -7874,7 +7892,19 @@ public class ECMA48 implements Runnable {
if (maybeTransparent) {
maybeTransparent = sixel.isTransparent();
}
imageToCells(image, true, maybeTransparent);
if (!sixelScrolling) {
int oldCursorX = currentState.cursorX;
int oldCursorY = currentState.cursorY;
currentState.cursorX = 0;
currentState.cursorY = 0;
imageToCells(image, false, maybeTransparent);
currentState.cursorX = oldCursorX;
currentState.cursorY = oldCursorY;
} else {
imageToCells(image, true, maybeTransparent);
}
}
/**
@ -8460,7 +8490,7 @@ public class ECMA48 implements Runnable {
// Room for more image on the visible screen.
currentState.cursorX++;
}
if (currentState.cursorY < scrollRegionBottom - 1) {
if (currentState.cursorY <= scrollRegionBottom - 1) {
// Not at the bottom, down a line.
linefeed();
} else if (scroll == true) {