X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2Ftterminal%2FECMA48.java;h=96f4e4083cc0bba8085d2df1311492214142017d;hb=aa77d68274fff56c0ceca162a687ea70795624ea;hp=7869829753df190c64306b51583731f3d812faec;hpb=f1c4c25e3e5c89aff7da36caaba1a94ecc379e4d;p=fanfix.git diff --git a/src/jexer/tterminal/ECMA48.java b/src/jexer/tterminal/ECMA48.java index 7869829..96f4e40 100644 --- a/src/jexer/tterminal/ECMA48.java +++ b/src/jexer/tterminal/ECMA48.java @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (C) 2016 Kevin Lamonte + * Copyright (C) 2017 Kevin Lamonte * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,6 +28,7 @@ */ package jexer.tterminal; +import java.io.BufferedOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; @@ -46,10 +47,12 @@ import jexer.event.TMouseEvent; import jexer.bits.Color; import jexer.bits.Cell; import jexer.bits.CellAttributes; +import jexer.io.ReadTimeoutException; +import jexer.io.TimeoutInputStream; import static jexer.TKeypress.*; /** - * This implements a complex ANSI ECMA-48/ISO 6429/ANSI X3.64 type consoles, + * This implements a complex ECMA-48/ISO 6429/ANSI X3.64 type console, * including a scrollback buffer. * *
@@ -129,15 +132,13 @@ public class ECMA48 implements Runnable {
return "\033[?6c";
case VT220:
+ case XTERM:
// "I am a VT220" - 7 bit version
if (!s8c1t) {
return "\033[?62;1;6c";
}
// "I am a VT220" - 8 bit version
return "\u009b?62;1;6c";
- case XTERM:
- // "I am a VT100 with advanced video option" (often VT102)
- return "\033[?1;2c";
default:
throw new IllegalArgumentException("Invalid device type: " + type);
}
@@ -203,7 +204,7 @@ public class ECMA48 implements Runnable {
*
* @param str string to send
*/
- private void writeRemote(final String str) {
+ public void writeRemote(final String str) {
if (stopReaderThread) {
// Reader hit EOF, bail out now.
close();
@@ -220,6 +221,7 @@ public class ECMA48 implements Runnable {
return;
}
try {
+ outputStream.flush();
for (int i = 0; i < str.length(); i++) {
outputStream.write(str.charAt(i));
}
@@ -234,6 +236,7 @@ public class ECMA48 implements Runnable {
return;
}
try {
+ output.flush();
output.write(str);
output.flush();
} catch (IOException e) {
@@ -252,77 +255,60 @@ public class ECMA48 implements Runnable {
*/
public final void close() {
- // Synchronize so we don't stomp on the reader thread.
- synchronized (this) {
-
- // Close the input stream
- switch (type) {
- case VT100:
- case VT102:
- case VT220:
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- // SQUASH
- }
- inputStream = null;
- }
- break;
- case XTERM:
- if (input != null) {
- try {
- input.close();
- } catch (IOException e) {
- // SQUASH
- }
- input = null;
- inputStream = null;
- }
- break;
+ // Tell the reader thread to stop looking at input. It will close
+ // the input streams.
+ if (stopReaderThread == false) {
+ stopReaderThread = true;
+ try {
+ readerThread.join(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
}
+ }
- // Tell the reader thread to stop looking at input.
- if (stopReaderThread == false) {
- stopReaderThread = true;
+ // Now close the output stream.
+ switch (type) {
+ case VT100:
+ case VT102:
+ case VT220:
+ if (outputStream != null) {
try {
- readerThread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
+ outputStream.close();
+ } catch (IOException e) {
+ // SQUASH
}
+ outputStream = null;
}
-
- // Close the output stream.
- switch (type) {
- case VT100:
- case VT102:
- case VT220:
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException e) {
- // SQUASH
- }
- outputStream = null;
+ break;
+ case XTERM:
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ // SQUASH
}
- break;
- case XTERM:
- if (output != null) {
- try {
- output.close();
- } catch (IOException e) {
- // SQUASH
- }
- output = null;
+ outputStream = null;
+ }
+ if (output != null) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ // SQUASH
}
- break;
- default:
- throw new IllegalArgumentException("Invalid device type: "
- + type);
+ output = null;
}
- } // synchronized (this)
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid device type: " +
+ type);
+ }
}
+ /**
+ * The enclosing listening object.
+ */
+ private DisplayListener displayListener;
+
/**
* When true, the reader thread is expected to exit.
*/
@@ -395,7 +381,7 @@ public class ECMA48 implements Runnable {
/**
* The terminal's raw InputStream. This is used for type != XTERM.
*/
- private volatile InputStream inputStream;
+ private volatile TimeoutInputStream inputStream;
/**
* The terminal's output. For type == XTERM, this wraps an
@@ -544,6 +530,22 @@ public class ECMA48 implements Runnable {
return width;
}
+ /**
+ * Set the display width.
+ *
+ * @param width the new width
+ */
+ public final void setWidth(final int width) {
+ this.width = width;
+ rightMargin = width - 1;
+ if (currentState.cursorX >= width) {
+ currentState.cursorX = width - 1;
+ }
+ if (savedState.cursorX >= width) {
+ savedState.cursorX = width - 1;
+ }
+ }
+
/**
* Physical display height. We start at 80x24, but the user can resize
* us bigger/smaller.
@@ -559,6 +561,35 @@ public class ECMA48 implements Runnable {
return height;
}
+ /**
+ * Set the display height.
+ *
+ * @param height the new height
+ */
+ public final void setHeight(final int height) {
+ this.height = height;
+ if (scrollRegionBottom >= height) {
+ scrollRegionBottom = height - 1;
+ }
+ if (scrollRegionTop >= scrollRegionBottom) {
+ scrollRegionTop = 0;
+ }
+ if (currentState.cursorY >= height) {
+ currentState.cursorY = height - 1;
+ }
+ if (savedState.cursorY >= height) {
+ savedState.cursorY = height - 1;
+ }
+ while (display.size() < height) {
+ DisplayLine line = new DisplayLine(currentState.attr);
+ line.setReverseColor(reverseVideo);
+ display.add(line);
+ }
+ while (display.size() > height) {
+ scrollback.add(display.remove(0));
+ }
+ }
+
/**
* Top margin of the scrolling region.
*/
@@ -867,6 +898,11 @@ public class ECMA48 implements Runnable {
arrowKeyMode = ArrowKeyMode.ANSI;
keypadMode = KeypadMode.Numeric;
wrapLineFlag = false;
+ if (displayListener != null) {
+ width = displayListener.getDisplayWidth();
+ height = displayListener.getDisplayHeight();
+ rightMargin = width - 1;
+ }
// Flags
shiftOut = false;
@@ -905,11 +941,14 @@ public class ECMA48 implements Runnable {
* @param outputStream an OutputStream connected to the remote user. For
* type == XTERM, outputStream is converted to a Writer with UTF-8
* encoding.
+ * @param displayListener a callback to the outer display, or null for
+ * default VT100 behavior
* @throws UnsupportedEncodingException if an exception is thrown when
* creating the InputStreamReader
*/
public ECMA48(final DeviceType type, final InputStream inputStream,
- final OutputStream outputStream) throws UnsupportedEncodingException {
+ final OutputStream outputStream, final DisplayListener displayListener)
+ throws UnsupportedEncodingException {
assert (inputStream != null);
assert (outputStream != null);
@@ -920,15 +959,21 @@ public class ECMA48 implements Runnable {
display = new LinkedList