import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
-import java.util.Map;
import jexer.TImage;
import jexer.bits.Cell;
* 1024.
*/
private static final int MAX_COLOR_REGISTERS = 1024;
+ // Black-and-white is possible too.
+ // private static final int MAX_COLOR_REGISTERS = 2;
// ------------------------------------------------------------------------
// Variables --------------------------------------------------------------
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];
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);
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);
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);
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);
// 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
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<TInputEvent>();
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<TInputEvent>();
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 ---------------------------------------------------------
// ------------------------------------------------------------------------
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 ---------------------------------------------------------------
// ------------------------------------------------------------------------
events.clear();
}
+ if (output.checkError()) {
+ // This is EOF.
+ done = true;
+ }
+
// Wait 20 millis for more data
Thread.sleep(20);
}
done = true;
}
} // while ((done == false) && (stopReaderThread == false))
+
+ // TODO: pass an event up to TApplication to tell it this Backend is
+ // done.
+
// System.err.println("*** run() exiting..."); System.err.flush();
}
// 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();
|| (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();
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);
}
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) {
*
* 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.
*/
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\\";
}
}