X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjexer%2Fbackend%2FECMA48Terminal.java;h=ed2715c834bc3402062690cd270b4846c4dae618;hb=3405b554b5a0567b3c22f146fc1ce226e3fa48d2;hp=05c7575e1914ea9658b47bf2ce79b473c602d936;hpb=1db1bc0261a09f2c40c504a9847437a00b51f459;p=fanfix.git diff --git a/src/jexer/backend/ECMA48Terminal.java b/src/jexer/backend/ECMA48Terminal.java index 05c7575..ed2715c 100644 --- a/src/jexer/backend/ECMA48Terminal.java +++ b/src/jexer/backend/ECMA48Terminal.java @@ -51,6 +51,7 @@ import jexer.TImage; import jexer.bits.Cell; import jexer.bits.CellAttributes; import jexer.bits.Color; +import jexer.bits.StringUtils; import jexer.event.TCommandEvent; import jexer.event.TInputEvent; import jexer.event.TKeypressEvent; @@ -242,11 +243,6 @@ public class ECMA48Terminal extends LogicalScreen */ private ImageCache jexerCache = null; - /** - * Base64 encoder used by iTerm2 and Jexer images. - */ - private java.util.Base64.Encoder base64 = null; - /** * If true, then we changed System.in and need to change it back. */ @@ -1172,11 +1168,12 @@ public class ECMA48Terminal extends LogicalScreen // Enable mouse reporting and metaSendsEscape this.output.printf("%s%s", mouse(true), xtermMetaSendsEscape(true)); - this.output.flush(); // Request xterm use the sixel settings we want this.output.printf("%s", xtermSetSixelSettings()); + this.output.flush(); + // Query the screen size sessionInfo.queryWindowSize(); setDimensions(sessionInfo.getWindowWidth(), @@ -1264,11 +1261,12 @@ public class ECMA48Terminal extends LogicalScreen // Enable mouse reporting and metaSendsEscape this.output.printf("%s%s", mouse(true), xtermMetaSendsEscape(true)); - this.output.flush(); // Request xterm use the sixel settings we want this.output.printf("%s", xtermSetSixelSettings()); + this.output.flush(); + // Query the screen size sessionInfo.queryWindowSize(); setDimensions(sessionInfo.getWindowWidth(), @@ -2240,10 +2238,13 @@ public class ECMA48Terminal extends LogicalScreen boolean eventMouse3 = false; boolean eventMouseWheelUp = false; boolean eventMouseWheelDown = false; + boolean eventAlt = false; + boolean eventCtrl = false; + boolean eventShift = false; // System.err.printf("buttons: %04x\r\n", buttons); - switch (buttons) { + switch (buttons & 0xE3) { case 0: eventMouse1 = true; mouse1 = true; @@ -2325,9 +2326,21 @@ public class ECMA48Terminal extends LogicalScreen eventType = TMouseEvent.Type.MOUSE_MOTION; break; } + + if ((buttons & 0x04) != 0) { + eventShift = true; + } + if ((buttons & 0x08) != 0) { + eventAlt = true; + } + if ((buttons & 0x10) != 0) { + eventCtrl = true; + } + return new TMouseEvent(eventType, x, y, x, y, eventMouse1, eventMouse2, eventMouse3, - eventMouseWheelUp, eventMouseWheelDown); + eventMouseWheelUp, eventMouseWheelDown, + eventAlt, eventCtrl, eventShift); } /** @@ -2362,12 +2375,15 @@ public class ECMA48Terminal extends LogicalScreen boolean eventMouse3 = false; boolean eventMouseWheelUp = false; boolean eventMouseWheelDown = false; + boolean eventAlt = false; + boolean eventCtrl = false; + boolean eventShift = false; if (release) { eventType = TMouseEvent.Type.MOUSE_UP; } - switch (buttons) { + switch (buttons & 0xE3) { case 0: eventMouse1 = true; break; @@ -2424,9 +2440,21 @@ public class ECMA48Terminal extends LogicalScreen // Unknown, bail out return null; } + + if ((buttons & 0x04) != 0) { + eventShift = true; + } + if ((buttons & 0x08) != 0) { + eventAlt = true; + } + if ((buttons & 0x10) != 0) { + eventCtrl = true; + } + return new TMouseEvent(eventType, x, y, x, y, eventMouse1, eventMouse2, eventMouse3, - eventMouseWheelUp, eventMouseWheelDown); + eventMouseWheelUp, eventMouseWheelDown, + eventAlt, eventCtrl, eventShift); } /** @@ -2858,12 +2886,20 @@ public class ECMA48Terminal extends LogicalScreen } jexerImages = true; } + if (x.equals("1337")) { + // Terminal reports iTerm2 images support + if (debugToStderr) { + System.err.println("Device Attributes: iTerm2 images"); + } + iterm2Images = true; + } } if (jexerImages == false) { // Terminal does not support Jexer images, disable // them. jexerImageOption = JexerImageOption.DISABLED; } + resetParser(); return; case 't': // windowOps @@ -3156,12 +3192,10 @@ public class ECMA48Terminal extends LogicalScreen int imageWidth = cells.get(0).getImage().getWidth(); int imageHeight = cells.get(0).getImage().getHeight(); - // cells.get(x).getImage() has a dithered bitmap containing indexes - // into the color palette. Piece these together into one larger - // image for final rendering. + // Piece these together into one larger image for final rendering. int totalWidth = 0; - int fullWidth = cells.size() * getTextWidth(); - int fullHeight = getTextHeight(); + int fullWidth = cells.size() * imageWidth; + int fullHeight = imageHeight; for (int i = 0; i < cells.size(); i++) { totalWidth += cells.get(i).getImage().getWidth(); } @@ -3171,10 +3205,8 @@ public class ECMA48Terminal extends LogicalScreen int [] rgbArray; for (int i = 0; i < cells.size() - 1; i++) { - int tileWidth = Math.min(cells.get(i).getImage().getWidth(), - imageWidth); - int tileHeight = Math.min(cells.get(i).getImage().getHeight(), - imageHeight); + int tileWidth = imageWidth; + int tileHeight = imageHeight; if (false && cells.get(i).isInvertedImage()) { // I used to put an all-white cell over the cursor, don't do @@ -3242,7 +3274,7 @@ public class ECMA48Terminal extends LogicalScreen image.setRGB((cells.size() - 1) * imageWidth, 0, totalWidth, imageHeight, rgbArray, 0, totalWidth); - if (totalWidth < getTextWidth()) { + if (totalWidth < imageWidth) { int backgroundColor = cells.get(cells.size() - 1).getBackground().getRGB(); for (int imageX = image.getWidth() - totalWidth; @@ -3254,6 +3286,22 @@ public class ECMA48Terminal extends LogicalScreen } } + if ((image.getWidth() != cells.size() * getTextWidth()) + || (image.getHeight() != getTextHeight()) + ) { + // Rescale the image to fit the text cells it is going into. + BufferedImage newImage; + newImage = new BufferedImage(cells.size() * getTextWidth(), + getTextHeight(), BufferedImage.TYPE_INT_ARGB); + + java.awt.Graphics gr = newImage.getGraphics(); + gr.drawImage(image, 0, 0, newImage.getWidth(), + newImage.getHeight(), null, null); + gr.dispose(); + image = newImage; + fullHeight = image.getHeight(); + } + // Dither the image. It is ok to lose the original here. if (palette == null) { palette = new SixelPalette(); @@ -3444,7 +3492,6 @@ public class ECMA48Terminal extends LogicalScreen if (iterm2Cache == null) { iterm2Cache = new ImageCache(height * 10); - base64 = java.util.Base64.getEncoder(); } // Save and get rows to/from the cache that do NOT have inverted @@ -3472,8 +3519,8 @@ public class ECMA48Terminal extends LogicalScreen // Piece cells.get(x).getImage() pieces together into one larger // image for final rendering. int totalWidth = 0; - int fullWidth = cells.size() * getTextWidth(); - int fullHeight = getTextHeight(); + int fullWidth = cells.size() * imageWidth; + int fullHeight = imageHeight; for (int i = 0; i < cells.size(); i++) { totalWidth += cells.get(i).getImage().getWidth(); } @@ -3483,10 +3530,8 @@ public class ECMA48Terminal extends LogicalScreen int [] rgbArray; for (int i = 0; i < cells.size() - 1; i++) { - int tileWidth = Math.min(cells.get(i).getImage().getWidth(), - imageWidth); - int tileHeight = Math.min(cells.get(i).getImage().getHeight(), - imageHeight); + int tileWidth = imageWidth; + int tileHeight = imageHeight; if (false && cells.get(i).isInvertedImage()) { // I used to put an all-white cell over the cursor, don't do // that anymore. @@ -3553,7 +3598,7 @@ public class ECMA48Terminal extends LogicalScreen image.setRGB((cells.size() - 1) * imageWidth, 0, totalWidth, imageHeight, rgbArray, 0, totalWidth); - if (totalWidth < getTextWidth()) { + if (totalWidth < imageWidth) { int backgroundColor = cells.get(cells.size() - 1).getBackground().getRGB(); for (int imageX = image.getWidth() - totalWidth; @@ -3565,6 +3610,22 @@ public class ECMA48Terminal extends LogicalScreen } } + if ((image.getWidth() != cells.size() * getTextWidth()) + || (image.getHeight() != getTextHeight()) + ) { + // Rescale the image to fit the text cells it is going into. + BufferedImage newImage; + newImage = new BufferedImage(cells.size() * getTextWidth(), + getTextHeight(), BufferedImage.TYPE_INT_ARGB); + + java.awt.Graphics gr = newImage.getGraphics(); + gr.drawImage(image, 0, 0, newImage.getWidth(), + newImage.getHeight(), null, null); + gr.dispose(); + image = newImage; + fullHeight = image.getHeight(); + } + /* * From https://iterm2.com/documentation-images.html: * @@ -3637,7 +3698,7 @@ public class ECMA48Terminal extends LogicalScreen getTextHeight()))); */ sb.append("inline=1:"); - sb.append(base64.encodeToString(pngOutputStream.toByteArray())); + sb.append(StringUtils.toBase64(pngOutputStream.toByteArray())); sb.append("\007"); if (saveInCache) { @@ -3694,7 +3755,6 @@ public class ECMA48Terminal extends LogicalScreen if (jexerCache == null) { jexerCache = new ImageCache(height * 10); - base64 = java.util.Base64.getEncoder(); } // Save and get rows to/from the cache that do NOT have inverted @@ -3722,8 +3782,8 @@ public class ECMA48Terminal extends LogicalScreen // Piece cells.get(x).getImage() pieces together into one larger // image for final rendering. int totalWidth = 0; - int fullWidth = cells.size() * getTextWidth(); - int fullHeight = getTextHeight(); + int fullWidth = cells.size() * imageWidth; + int fullHeight = imageHeight; for (int i = 0; i < cells.size(); i++) { totalWidth += cells.get(i).getImage().getWidth(); } @@ -3733,10 +3793,8 @@ public class ECMA48Terminal extends LogicalScreen int [] rgbArray; for (int i = 0; i < cells.size() - 1; i++) { - int tileWidth = Math.min(cells.get(i).getImage().getWidth(), - imageWidth); - int tileHeight = Math.min(cells.get(i).getImage().getHeight(), - imageHeight); + int tileWidth = imageWidth; + int tileHeight = imageHeight; if (false && cells.get(i).isInvertedImage()) { // I used to put an all-white cell over the cursor, don't do // that anymore. @@ -3803,7 +3861,7 @@ public class ECMA48Terminal extends LogicalScreen image.setRGB((cells.size() - 1) * imageWidth, 0, totalWidth, imageHeight, rgbArray, 0, totalWidth); - if (totalWidth < getTextWidth()) { + if (totalWidth < imageWidth) { int backgroundColor = cells.get(cells.size() - 1).getBackground().getRGB(); for (int imageX = image.getWidth() - totalWidth; @@ -3815,6 +3873,22 @@ public class ECMA48Terminal extends LogicalScreen } } + if ((image.getWidth() != cells.size() * getTextWidth()) + || (image.getHeight() != getTextHeight()) + ) { + // Rescale the image to fit the text cells it is going into. + BufferedImage newImage; + newImage = new BufferedImage(cells.size() * getTextWidth(), + getTextHeight(), BufferedImage.TYPE_INT_ARGB); + + java.awt.Graphics gr = newImage.getGraphics(); + gr.drawImage(image, 0, 0, newImage.getWidth(), + newImage.getHeight(), null, null); + gr.dispose(); + image = newImage; + fullHeight = image.getHeight(); + } + if (jexerImageOption == JexerImageOption.PNG) { // Encode as PNG ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream(1024); @@ -3832,7 +3906,7 @@ public class ECMA48Terminal extends LogicalScreen } sb.append("\033]444;1;0;"); - sb.append(base64.encodeToString(pngOutputStream.toByteArray())); + sb.append(StringUtils.toBase64(pngOutputStream.toByteArray())); sb.append("\007"); } else if (jexerImageOption == JexerImageOption.JPG) { @@ -3864,7 +3938,7 @@ public class ECMA48Terminal extends LogicalScreen } sb.append("\033]444;2;0;"); - sb.append(base64.encodeToString(jpgOutputStream.toByteArray())); + sb.append(StringUtils.toBase64(jpgOutputStream.toByteArray())); sb.append("\007"); } else if (jexerImageOption == JexerImageOption.RGB) { @@ -3883,7 +3957,7 @@ public class ECMA48Terminal extends LogicalScreen bytes[(py * stride * 3) + (px * 3) + 2] = (byte) ( rgb & 0xFF); } } - sb.append(base64.encodeToString(bytes)); + sb.append(StringUtils.toBase64(bytes)); sb.append("\007"); }