X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2Fbackend%2FECMA48Terminal.java;h=92758ee6a65e096072af59d53c5bca973f8469c0;hb=eb0d6c82905932e04acfb4066ab680ef867931ce;hp=1dc3957d75b534deec2b318a9c2bd501db8d7f5f;hpb=a69ed767c9c07cf35cf1c5f7821fc009cfe79cd2;p=nikiroo-utils.git diff --git a/src/jexer/backend/ECMA48Terminal.java b/src/jexer/backend/ECMA48Terminal.java index 1dc3957..92758ee 100644 --- a/src/jexer/backend/ECMA48Terminal.java +++ b/src/jexer/backend/ECMA48Terminal.java @@ -45,7 +45,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.LinkedList; -import java.util.Map; import jexer.TImage; import jexer.bits.Cell; @@ -86,6 +85,8 @@ public class ECMA48Terminal extends LogicalScreen * 1024. */ private static final int MAX_COLOR_REGISTERS = 1024; + // Black-and-white is possible too. + // private static final int MAX_COLOR_REGISTERS = 2; // ------------------------------------------------------------------------ // Variables -------------------------------------------------------------- @@ -343,6 +344,16 @@ public class ECMA48Terminal extends LogicalScreen int green = (color >>> 8) & 0xFF; int blue = color & 0xFF; + if (MAX_COLOR_REGISTERS == 2) { + if (((red * red) + (green * green) + (blue * blue)) < 35568) { + // Black + return 0; + } + // White + return 1; + } + + rgbToHsl(red, green, blue, hsl); int hue = hsl[0]; int sat = hsl[1]; @@ -480,9 +491,9 @@ public class ECMA48Terminal extends LogicalScreen int red, green, blue; if (imageX < image.getWidth() - 1) { int pXpY = ditheredImage.getRGB(imageX + 1, imageY); - red = (int) ((pXpY >>> 16) & 0xFF) + (7 * redError); - green = (int) ((pXpY >>> 8) & 0xFF) + (7 * greenError); - blue = (int) ( pXpY & 0xFF) + (7 * blueError); + red = ((pXpY >>> 16) & 0xFF) + (7 * redError); + green = ((pXpY >>> 8) & 0xFF) + (7 * greenError); + blue = ( pXpY & 0xFF) + (7 * blueError); red = clamp(red); green = clamp(green); blue = clamp(blue); @@ -493,9 +504,9 @@ public class ECMA48Terminal extends LogicalScreen if (imageY < image.getHeight() - 1) { int pXpYp = ditheredImage.getRGB(imageX + 1, imageY + 1); - red = (int) ((pXpYp >>> 16) & 0xFF) + redError; - green = (int) ((pXpYp >>> 8) & 0xFF) + greenError; - blue = (int) ( pXpYp & 0xFF) + blueError; + red = ((pXpYp >>> 16) & 0xFF) + redError; + green = ((pXpYp >>> 8) & 0xFF) + greenError; + blue = ( pXpYp & 0xFF) + blueError; red = clamp(red); green = clamp(green); blue = clamp(blue); @@ -509,9 +520,9 @@ public class ECMA48Terminal extends LogicalScreen int pXYp = ditheredImage.getRGB(imageX, imageY + 1); - red = (int) ((pXmYp >>> 16) & 0xFF) + (3 * redError); - green = (int) ((pXmYp >>> 8) & 0xFF) + (3 * greenError); - blue = (int) ( pXmYp & 0xFF) + (3 * blueError); + red = ((pXmYp >>> 16) & 0xFF) + (3 * redError); + green = ((pXmYp >>> 8) & 0xFF) + (3 * greenError); + blue = ( pXmYp & 0xFF) + (3 * blueError); red = clamp(red); green = clamp(green); blue = clamp(blue); @@ -519,9 +530,9 @@ public class ECMA48Terminal extends LogicalScreen pXmYp |= ((green & 0xFF) << 8) | (blue & 0xFF); ditheredImage.setRGB(imageX - 1, imageY + 1, pXmYp); - red = (int) ((pXYp >>> 16) & 0xFF) + (5 * redError); - green = (int) ((pXYp >>> 8) & 0xFF) + (5 * greenError); - blue = (int) ( pXYp & 0xFF) + (5 * blueError); + red = ((pXYp >>> 16) & 0xFF) + (5 * redError); + green = ((pXYp >>> 8) & 0xFF) + (5 * greenError); + blue = ( pXYp & 0xFF) + (5 * blueError); red = clamp(red); green = clamp(green); blue = clamp(blue); @@ -663,6 +674,14 @@ public class ECMA48Terminal extends LogicalScreen // map the BufferedImage colors to their nearest neighbor in RGB // space. + if (MAX_COLOR_REGISTERS == 2) { + rgbColors.add(0); + rgbColors.add(0xFFFFFF); + rgbSortedIndex[0] = 0; + rgbSortedIndex[1] = 1; + return; + } + // We build a palette using the Hue-Saturation-Luminence model, // with 5+ bits for Hue, 2+ bits for Saturation, and 1+ bit for // Luminance. We convert these colors to 24-bit RGB, sort them @@ -1085,23 +1104,7 @@ public class ECMA48Terminal extends LogicalScreen windowResize = new TResizeEvent(TResizeEvent.Type.SCREEN, sessionInfo.getWindowWidth(), sessionInfo.getWindowHeight()); - // Permit RGB colors only if externally requested. - if (System.getProperty("jexer.ECMA48.rgbColor") != null) { - if (System.getProperty("jexer.ECMA48.rgbColor").equals("true")) { - doRgbColor = true; - } else { - doRgbColor = false; - } - } - - // Pull the system properties for sixel output. - if (System.getProperty("jexer.ECMA48.sixel") != null) { - if (System.getProperty("jexer.ECMA48.sixel").equals("true")) { - sixel = true; - } else { - sixel = false; - } - } + reloadOptions(); // Spin up the input reader eventQueue = new LinkedList(); @@ -1187,23 +1190,7 @@ public class ECMA48Terminal extends LogicalScreen windowResize = new TResizeEvent(TResizeEvent.Type.SCREEN, sessionInfo.getWindowWidth(), sessionInfo.getWindowHeight()); - // Permit RGB colors only if externally requested - if (System.getProperty("jexer.ECMA48.rgbColor") != null) { - if (System.getProperty("jexer.ECMA48.rgbColor").equals("true")) { - doRgbColor = true; - } else { - doRgbColor = false; - } - } - - // Pull the system properties for sixel output. - if (System.getProperty("jexer.ECMA48.sixel") != null) { - if (System.getProperty("jexer.ECMA48.sixel").equals("true")) { - sixel = true; - } else { - sixel = false; - } - } + reloadOptions(); // Spin up the input reader eventQueue = new LinkedList(); @@ -1270,6 +1257,19 @@ public class ECMA48Terminal extends LogicalScreen flush(); } + /** + * Resize the physical screen to match the logical screen dimensions. + */ + @Override + public void resizeToScreen() { + // Send dtterm/xterm sequences, which will probably not work because + // allowWindowOps is defaulted to false. + String resizeString = String.format("\033[8;%d;%dt", getHeight(), + getWidth()); + this.output.write(resizeString); + this.output.flush(); + } + // ------------------------------------------------------------------------ // TerminalReader --------------------------------------------------------- // ------------------------------------------------------------------------ @@ -1357,6 +1357,27 @@ public class ECMA48Terminal extends LogicalScreen this.listener = listener; } + /** + * Reload options from System properties. + */ + public void reloadOptions() { + // Permit RGB colors only if externally requested. + if (System.getProperty("jexer.ECMA48.rgbColor", + "false").equals("true") + ) { + doRgbColor = true; + } else { + doRgbColor = false; + } + + // Pull the system properties for sixel output. + if (System.getProperty("jexer.ECMA48.sixel", "true").equals("true")) { + sixel = true; + } else { + sixel = false; + } + } + // ------------------------------------------------------------------------ // Runnable --------------------------------------------------------------- // ------------------------------------------------------------------------ @@ -1434,6 +1455,11 @@ public class ECMA48Terminal extends LogicalScreen events.clear(); } + if (output.checkError()) { + // This is EOF. + done = true; + } + // Wait 20 millis for more data Thread.sleep(20); } @@ -1445,7 +1471,11 @@ public class ECMA48Terminal extends LogicalScreen done = true; } } // while ((done == false) && (stopReaderThread == false)) - // System.err.println("*** run() exiting..."); System.err.flush(); + + // TODO: pass an event up to TApplication to tell it this Backend is + // done. + + System.err.println("*** run() exiting..."); System.err.flush(); } // ------------------------------------------------------------------------ @@ -2224,6 +2254,9 @@ public class ECMA48Terminal extends LogicalScreen // Check for new window size long windowSizeDelay = nowTime - windowSizeTime; if (windowSizeDelay > 1000) { + int oldTextWidth = getTextWidth(); + int oldTextHeight = getTextHeight(); + sessionInfo.queryWindowSize(); int newWidth = sessionInfo.getWindowWidth(); int newHeight = sessionInfo.getWindowHeight(); @@ -2232,14 +2265,24 @@ public class ECMA48Terminal extends LogicalScreen || (newHeight != windowResize.getHeight()) ) { + // Request xterm report window dimensions in pixels again. + // Between now and then, ensure that the reported text cell + // size is the same by setting widthPixels and heightPixels + // to match the new dimensions. + widthPixels = oldTextWidth * newWidth; + heightPixels = oldTextHeight * newHeight; + if (debugToStderr) { System.err.println("Screen size changed, old size " + windowResize); System.err.println(" new size " + newWidth + " x " + newHeight); + System.err.println(" old pixels " + + oldTextWidth + " x " + oldTextHeight); + System.err.println(" new pixels " + + getTextWidth() + " x " + getTextHeight()); } - // Request xterm report window dimensions in pixels again. this.output.printf("%s", xtermReportWindowPixelDimensions()); this.output.flush(); @@ -2745,11 +2788,19 @@ public class ECMA48Terminal extends LogicalScreen StringBuilder sb = new StringBuilder(); - assert (sixel == true); assert (cells != null); assert (cells.size() > 0); assert (cells.get(0).getImage() != null); + if (sixel == false) { + sb.append(normal()); + sb.append(gotoXY(x, y)); + for (int i = 0; i < cells.size(); i++) { + sb.append(' '); + } + return sb.toString(); + } + if (sixelCache == null) { sixelCache = new SixelCache(height * 10); } @@ -2801,6 +2852,15 @@ public class ECMA48Terminal extends LogicalScreen rgbArray = cells.get(i).getImage().getRGB(0, 0, imageWidth, imageHeight, null, 0, imageWidth); } + + /* + System.err.printf("calling image.setRGB(): %d %d %d %d %d\n", + i * imageWidth, 0, imageWidth, imageHeight, + 0, imageWidth); + System.err.printf(" fullWidth %d fullHeight %d cells.size() %d textWidth %d\n", + fullWidth, fullHeight, cells.size(), getTextWidth()); + */ + image.setRGB(i * imageWidth, 0, imageWidth, imageHeight, rgbArray, 0, imageWidth); if (imageHeight < fullHeight) { @@ -3388,6 +3448,11 @@ public class ECMA48Terminal extends LogicalScreen * * Note that this also sets the alternate/primary screen buffer. * + * Finally, also emit a Privacy Message sequence that Jexer recognizes to + * mean "hide the mouse pointer." We have to use our own sequence to do + * this because there is no standard in xterm for unilaterally hiding the + * pointer all the time (regardless of typing). + * * @param on If true, enable mouse report and use the alternate screen * buffer. If false disable mouse reporting and use the primary screen * buffer. @@ -3395,9 +3460,9 @@ public class ECMA48Terminal extends LogicalScreen */ private String mouse(final boolean on) { if (on) { - return "\033[?1002;1003;1005;1006h\033[?1049h"; + return "\033[?1002;1003;1005;1006h\033[?1049h\033^hideMousePointer\033\\"; } - return "\033[?1002;1003;1006;1005l\033[?1049l"; + return "\033[?1002;1003;1006;1005l\033[?1049l\033^showMousePointer\033\\"; } }