--- /dev/null
+/**
+ * Jexer - Java Text User Interface
+ *
+ * Version: $Id$
+ *
+ * Author: Kevin Lamonte, <a href="mailto:kevin.lamonte@gmail.com">kevin.lamonte@gmail.com</a>
+ *
+ * License: LGPLv3 or later
+ *
+ * Copyright: This module is licensed under the GNU Lesser General
+ * Public License Version 3. Please see the file "COPYING" in this
+ * directory for more information about the GNU Lesser General Public
+ * License Version 3.
+ *
+ * Copyright (C) 2015 Kevin Lamonte
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * http://www.gnu.org/licenses/, or write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+package jexer.backend;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import jexer.event.TInputEvent;
+import jexer.io.ECMA48Screen;
+import jexer.io.ECMA48Terminal;
+
+/**
+ * This class uses an xterm/ANSI X3.64/ECMA-48 type terminal to provide a
+ * screen, keyboard, and mouse to TApplication.
+ */
+public class ECMA48Backend extends Backend {
+
+ /**
+ * Input events are processed by this Terminal.
+ */
+ private ECMA48Terminal terminal;
+
+ /**
+ * Public constructor.
+ *
+ * @param input an InputStream connected to the remote user, or null for
+ * System.in. If System.in is used, then on non-Windows systems it will
+ * be put in raw mode; shutdown() will (blindly!) put System.in in cooked
+ * mode. input is always converted to a Reader with UTF-8 encoding.
+ * @param output an OutputStream connected to the remote user, or null
+ * for System.out. output is always converted to a Writer with UTF-8
+ * encoding.
+ */
+ public ECMA48Backend(InputStream input, OutputStream output) throws UnsupportedEncodingException {
+
+ // Create a terminal and explicitly set stdin into raw mode
+ terminal = new ECMA48Terminal(input, output);
+
+ // Create a screen
+ screen = new ECMA48Screen(terminal);
+
+ // Clear the screen
+ terminal.getOutput().write(terminal.clearAll());
+ terminal.flush();
+ }
+
+ /**
+ * Sync the logical screen to the physical device.
+ */
+ @Override
+ public void flushScreen() {
+ screen.flushPhysical();
+ }
+
+ /**
+ * Get keyboard, mouse, and screen resize events.
+ *
+ * @param timeout maximum amount of time (in millis) to wait for an
+ * event. 0 means to return immediately, i.e. perform a poll.
+ * @return events received, or an empty list if the timeout was reached
+ * first
+ */
+ @Override
+ public List<TInputEvent> getEvents(int timeout) {
+ return terminal.getEvents();
+ }
+
+ /**
+ * Subclasses must provide an implementation that closes sockets,
+ * restores console, etc.
+ */
+ @Override
+ public void shutdown() {
+ terminal.shutdown();
+ }
+
+}
}
/**
- * Parses the next character of input to see if an InputEvent is
- * fully here.
+ * Return any events in the IO queue.
*
- * Params:
- * ch = Unicode code point
- * noChar = if true, ignore ch. This is currently used to
- * return a bare ESC and RESIZE events.
+ * @return list of new events (which may be empty)
+ */
+ public List<TInputEvent> getEvents() {
+ List<TInputEvent> events = new LinkedList<TInputEvent>();
+ return events;
+ }
+
+ /**
+ * Parses the next character of input to see if an InputEvent is fully
+ * here.
*
- * Returns:
- * list of new events (which may be empty)
+ * @param ch Unicode code point
+ * @return list of new events (which may be empty)
*/
public List<TInputEvent> getEvents(char ch) {
return getEvents(ch, false);
* Parses the next character of input to see if an InputEvent is
* fully here.
*
- * Params:
- * ch = Unicode code point
- * noChar = if true, ignore ch. This is currently used to
- * return a bare ESC and RESIZE events.
- *
- * Returns:
- * list of new events (which may be empty)
+ * @param ch Unicode code point
+ * @param noChar if true, ignore ch. This is currently used to return a
+ * bare ESC and RESIZE events.
+ * @return list of new events (which may be empty)
*/
public List<TInputEvent> getEvents(char ch, boolean noChar) {
List<TInputEvent> events = new LinkedList<TInputEvent>();
}
/**
- * Tell (u)xterm that we want alt- keystrokes to send escape +
- * character rather than set the 8th bit. Anyone who wants UTF8
- * should want this enabled.
+ * Tell (u)xterm that we want alt- keystrokes to send escape + character
+ * rather than set the 8th bit. Anyone who wants UTF8 should want this
+ * enabled.
*
- * Params:
- * on = if true, enable metaSendsEscape
- *
- * Returns:
- * the string to emit to xterm
+ * @param on if true, enable metaSendsEscape
+ * @return the string to emit to xterm
*/
static public String xtermMetaSendsEscape(boolean on) {
if (on) {
}
/**
- * Convert a list of SGR parameters into a full escape sequence.
- * This also eliminates a trailing ';' which would otherwise reset
- * everything to white-on-black not-bold.
- *
- * Params:
- * str = string of parameters, e.g. "31;1;"
+ * Convert a list of SGR parameters into a full escape sequence. This
+ * also eliminates a trailing ';' which would otherwise reset everything
+ * to white-on-black not-bold.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[31;1m"
+ * @param str string of parameters, e.g. "31;1;"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[31;1m"
*/
static public String addHeaderSGR(String str) {
if (str.length() > 0) {
/**
* Create a SGR parameter sequence for a single color change.
*
- * Params:
- * color = one of the Color.WHITE, Color.BLUE, etc. constants
- * foreground = if true, this is a foreground color
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[42m"
+ * @param color one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param foreground if true, this is a foreground color
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[42m"
*/
static public String color(Color color, boolean foreground) {
return color(color, foreground, true);
/**
* Create a SGR parameter sequence for a single color change.
*
- * Params:
- * color = one of the Color.WHITE, Color.BLUE, etc. constants
- * foreground = if true, this is a foreground color
- * header = if true, make the full header, otherwise just emit
- * the color parameter e.g. "42;"
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[42m"
+ * @param color one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param foreground if true, this is a foreground color
+ * @param header if true, make the full header, otherwise just emit the
+ * color parameter e.g. "42;"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[42m"
*/
static public String color(Color color, boolean foreground,
boolean header) {
* Create a SGR parameter sequence for both foreground and
* background color change.
*
- * Params:
- * foreColor = one of the Color.WHITE, Color.BLUE, etc. constants
- * backColor = one of the Color.WHITE, Color.BLUE, etc. constants
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[31;42m"
+ * @param foreColor one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param backColor one of the Color.WHITE, Color.BLUE, etc. constants
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[31;42m"
*/
static public String color(Color foreColor, Color backColor) {
return color(foreColor, backColor, true);
* Create a SGR parameter sequence for both foreground and
* background color change.
*
- * Params:
- * foreColor = one of the Color.WHITE, Color.BLUE, etc. constants
- * backColor = one of the Color.WHITE, Color.BLUE, etc. constants
- * header = if true, make the full header, otherwise just emit
- * the color parameter e.g. "31;42;"
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[31;42m"
+ * @param foreColor one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param backColor one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param header if true, make the full header, otherwise just emit the
+ * color parameter e.g. "31;42;"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[31;42m"
*/
static public String color(Color foreColor, Color backColor,
boolean header) {
/**
* Create a SGR parameter sequence for foreground, background, and
- * several attributes. This sequence first resets all attributes
- * to default, then sets attributes as per the parameters.
- *
- * Params:
- * foreColor = one of the Color.WHITE, Color.BLUE, etc. constants
- * backColor = one of the Color.WHITE, Color.BLUE, etc. constants
- * bold = if true, set bold
- * reverse = if true, set reverse
- * blink = if true, set blink
- * underline = if true, set underline
+ * several attributes. This sequence first resets all attributes to
+ * default, then sets attributes as per the parameters.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[0;1;31;42m"
+ * @param foreColor one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param backColor one of the Color.WHITE, Color.BLUE, etc. constants
+ * @param bold if true, set bold
+ * @param reverse if true, set reverse
+ * @param blink if true, set blink
+ * @param underline if true, set underline
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[0;1;31;42m"
*/
static public String color(Color foreColor, Color backColor, boolean bold,
boolean reverse, boolean blink, boolean underline) {
/**
* Create a SGR parameter sequence for enabling reverse color.
*
- * Params:
- * on = if true, turn on reverse
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[7m"
+ * @param on if true, turn on reverse
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[7m"
*/
static public String reverse(boolean on) {
if (on) {
/**
* Create a SGR parameter sequence to reset to defaults.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[0m"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[0m"
*/
static public String normal() {
return normal(true);
/**
* Create a SGR parameter sequence to reset to defaults.
*
- * Params:
- * header = if true, make the full header, otherwise just emit
- * the bare parameter e.g. "0;"
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[0m"
+ * @param header if true, make the full header, otherwise just emit the
+ * bare parameter e.g. "0;"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[0m"
*/
static public String normal(boolean header) {
if (header) {
/**
* Create a SGR parameter sequence for enabling boldface.
*
- * Params:
- * on = if true, turn on bold
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[1m"
+ * @param on if true, turn on bold
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[1m"
*/
static public String bold(boolean on) {
return bold(on, true);
/**
* Create a SGR parameter sequence for enabling boldface.
*
- * Params:
- * on = if true, turn on bold
- * header = if true, make the full header, otherwise just emit
- * the bare parameter e.g. "1;"
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[1m"
+ * @param on if true, turn on bold
+ * @param header if true, make the full header, otherwise just emit the
+ * bare parameter e.g. "1;"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[1m"
*/
static public String bold(boolean on, boolean header) {
if (header) {
/**
* Create a SGR parameter sequence for enabling blinking text.
*
- * Params:
- * on = if true, turn on blink
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[5m"
+ * @param on if true, turn on blink
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[5m"
*/
static public String blink(boolean on) {
return blink(on, true);
/**
* Create a SGR parameter sequence for enabling blinking text.
*
- * Params:
- * on = if true, turn on blink
- * header = if true, make the full header, otherwise just emit
- * the bare parameter e.g. "5;"
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[5m"
+ * @param on if true, turn on blink
+ * @param header if true, make the full header, otherwise just emit the
+ * bare parameter e.g. "5;"
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[5m"
*/
static public String blink(boolean on, boolean header) {
if (header) {
}
/**
- * Create a SGR parameter sequence for enabling underline /
- * underscored text.
- *
- * Params:
- * on = if true, turn on underline
+ * Create a SGR parameter sequence for enabling underline / underscored
+ * text.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal, e.g. "\033[4m"
+ * @param on if true, turn on underline
+ * @return the string to emit to an ANSI / ECMA-style terminal,
+ * e.g. "\033[4m"
*/
static public String underline(boolean on) {
if (on) {
/**
* Create a SGR parameter sequence for enabling the visible cursor.
*
- * Params:
- * on = if true, turn on cursor
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @param on if true, turn on cursor
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
public String cursor(boolean on) {
if (on && (cursorOn == false)) {
* Clear the entire screen. Because some terminals use back-color-erase,
* set the color to white-on-black beforehand.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
static public String clearAll() {
return "\033[0;37;40m\033[2J";
* Because some terminals use back-color-erase, set the color to
* white-on-black beforehand.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
static public String clearRemainingLine() {
return "\033[0;37;40m\033[K";
* Clear the line up the cursor (inclusive). Because some terminals use
* back-color-erase, set the color to white-on-black beforehand.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
static public String clearPreceedingLine() {
return "\033[0;37;40m\033[1K";
* Clear the line. Because some terminals use back-color-erase, set the
* color to white-on-black beforehand.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
static public String clearLine() {
return "\033[0;37;40m\033[2K";
/**
* Move the cursor to the top-left corner.
*
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
static public String home() {
return "\033[H";
/**
* Move the cursor to (x, y).
*
- * Params:
- * x = column coordinate. 0 is the left-most column.
- * y = row coordinate. 0 is the top-most row.
- *
- * Returns:
- * the string to emit to an ANSI / ECMA-style terminal
+ * @param x column coordinate. 0 is the left-most column.
+ * @param y row coordinate. 0 is the top-most row.
+ * @return the string to emit to an ANSI / ECMA-style terminal
*/
static public String gotoXY(int x, int y) {
return String.format("\033[%d;%dH", y + 1, x + 1);
}
/**
- * Tell (u)xterm that we want to receive mouse events based on
- * "Any event tracking" and UTF-8 coordinates. See
+ * Tell (u)xterm that we want to receive mouse events based on "Any event
+ * tracking" and UTF-8 coordinates. See
* http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
*
- * Finally, this sets the alternate screen buffer.
- *
- * Params:
- * on = if true, enable mouse report
+ * Note that this also sets the alternate/primary screen buffer.
*
- * Returns:
- * the string to emit to xterm
+ * @param on If true, enable mouse report and use the alternate screen
+ * buffer. If false disable mouse reporting and use the primary screen
+ * buffer.
+ * @return the string to emit to xterm
*/
static public String mouse(boolean on) {
if (on) {