From 7b5261bc5b641e0769902f014e3b21f61050b02b Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Wed, 11 Mar 2015 14:29:26 -0400 Subject: [PATCH] checkstyle'd --- README.md | 17 +- build.xml | 2 +- src/jexer/TApplication.java | 601 +++---- src/jexer/TCommand.java | 252 +-- src/jexer/TKeypress.java | 1393 +++++++-------- src/jexer/backend/Backend.java | 47 +- src/jexer/backend/ECMA48Backend.java | 103 +- src/jexer/backend/package-info.java | 36 + src/jexer/bits/Cell.java | 151 +- src/jexer/bits/CellAttributes.java | 320 ++-- src/jexer/bits/Color.java | 233 ++- src/jexer/bits/ColorTheme.java | 703 ++++---- src/jexer/bits/GraphicsChars.java | 193 ++- src/jexer/bits/MnemonicString.java | 89 +- src/jexer/bits/package-info.java | 36 + src/jexer/event/TCommandEvent.java | 46 +- src/jexer/event/TInputEvent.java | 39 +- src/jexer/event/TKeypressEvent.java | 34 +- src/jexer/event/TMenuEvent.java | 42 +- src/jexer/event/TMouseEvent.java | 95 +- src/jexer/event/TResizeEvent.java | 84 +- src/jexer/event/package-info.java | 36 + src/jexer/io/ECMA48Screen.java | 423 ++--- src/jexer/io/ECMA48Terminal.java | 2282 +++++++++++++------------ src/jexer/io/Screen.java | 642 +++---- src/jexer/io/package-info.java | 36 + src/jexer/package-info.java | 73 + src/jexer/session/SessionInfo.java | 28 +- src/jexer/session/TSessionInfo.java | 56 +- src/jexer/session/TTYSessionInfo.java | 183 +- src/jexer/session/package-info.java | 36 + 31 files changed, 4479 insertions(+), 3832 deletions(-) create mode 100644 src/jexer/backend/package-info.java create mode 100644 src/jexer/bits/package-info.java create mode 100644 src/jexer/event/package-info.java create mode 100644 src/jexer/io/package-info.java create mode 100644 src/jexer/package-info.java create mode 100644 src/jexer/session/package-info.java diff --git a/README.md b/README.md index cc1d44c..ced2867 100644 --- a/README.md +++ b/README.md @@ -60,21 +60,26 @@ version 1.0: 0.0.1: - Base classes: + - TCommand use getters/setters + - TCommand.Type: switch to int so that subclasses can make more + kinds of commands + - TKeypress use getters/setters to make immutable + - TKeypressEvent use getters/setters to make immutable + - TMouseEvent use getters/setters to make immutable +- Get a movable window on screen - TWidget - TWindow -- package-info's -- Incorporate checkstyle ant task - - Fix all noted issues except use of tabs + - TLabel 0.0.2: -- Get modal messagebox running without fibers (use two reader threads - with syncronization, don't bother with coroutines) - Port remaining d-tui functionality over - - All widgets + - All widgets except modal (e.g. messagebox/fileopen) 0.0.3: +- Get modal messagebox running without fibers (use two reader threads + with syncronization, don't bother with coroutines) - TEditor, fixup keyboard movement 0.0.4: diff --git a/build.xml b/build.xml index da82c0f..06733d7 100644 --- a/build.xml +++ b/build.xml @@ -90,7 +90,7 @@ - Test]]> + Jexer - Java Text User Interface Library]]> Copyright © 2015 Kevin Lamonte. Licensed LGPLv3+]]> diff --git a/src/jexer/TApplication.java b/src/jexer/TApplication.java index 52bd435..e9256a1 100644 --- a/src/jexer/TApplication.java +++ b/src/jexer/TApplication.java @@ -1,16 +1,11 @@ /** - * Jexer - Java Text User Interface - demonstration program - * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com + * Jexer - Java Text User Interface * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer; @@ -59,27 +57,36 @@ public class TApplication { /** * Access to the physical screen, keyboard, and mouse. */ - public Backend backend; + private Backend backend; /** - * Actual mouse coordinate X + * Actual mouse coordinate X. */ private int mouseX; /** - * Actual mouse coordinate Y + * Actual mouse coordinate Y. */ private int mouseY; /** - * Event queue that will be drained by either primary or secondary Fiber + * Event queue that will be drained by either primary or secondary Fiber. */ private List eventQueue; /** * Windows and widgets pull colors from this ColorTheme. */ - public ColorTheme theme; + private ColorTheme theme; + + /** + * Get the color theme. + * + * @return the theme + */ + public final ColorTheme getTheme() { + return theme; + } /** * When true, exit the application. @@ -97,9 +104,11 @@ public class TApplication { public boolean flush = false; /** - * Y coordinate of the top edge of the desktop. + * Y coordinate of the top edge of the desktop. For now this is a + * constant. Someday it would be nice to have a multi-line menu or + * toolbars. */ - static public final int desktopTop = 1; + public static final int desktopTop = 1; /** * Y coordinate of the bottom edge of the desktop. @@ -116,184 +125,187 @@ public class TApplication { * @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. + * @throws UnsupportedEncodingException if an exception is thrown when + * creating the InputStreamReader */ - public TApplication(InputStream input, OutputStream output) throws UnsupportedEncodingException { + public TApplication(final InputStream input, + final OutputStream output) throws UnsupportedEncodingException { - backend = new ECMA48Backend(input, output); - theme = new ColorTheme(); - desktopBottom = backend.screen.getHeight() - 1; - eventQueue = new LinkedList(); + backend = new ECMA48Backend(input, output); + theme = new ColorTheme(); + desktopBottom = backend.getScreen().getHeight() - 1; + eventQueue = new LinkedList(); } /** * Invert the cell at the mouse pointer position. */ private void drawMouse() { - CellAttributes attr = backend.screen.getAttrXY(mouseX, mouseY); - attr.foreColor = attr.foreColor.invert(); - attr.backColor = attr.backColor.invert(); - backend.screen.putAttrXY(mouseX, mouseY, attr, false); - flush = true; - - /* - if (windows.length == 0) { - repaint = true; - } - */ - // TODO: remove this repaint after the above if (windows.length == 0) - // can be used again. - repaint = true; + CellAttributes attr = backend.getScreen().getAttrXY(mouseX, mouseY); + attr.setForeColor(attr.getForeColor().invert()); + attr.setBackColor(attr.getBackColor().invert()); + backend.getScreen().putAttrXY(mouseX, mouseY, attr, false); + flush = true; + + /* + if (windows.length == 0) { + repaint = true; + } + */ + // TODO: remove this repaint after the above if (windows.length == 0) + // can be used again. + repaint = true; } /** * Draw everything. */ - final public void drawAll() { - if ((flush) && (!repaint)) { - backend.flushScreen(); - flush = false; - return; - } - - if (!repaint) { - return; - } - - // If true, the cursor is not visible - boolean cursor = false; - - // Start with a clean screen - backend.screen.clear(); - - // Draw the background - CellAttributes background = theme.getColor("tapplication.background"); - backend.screen.putAll(GraphicsChars.HATCH, background); - - /* - // Draw each window in reverse Z order - TWindow [] sorted = windows.dup; - sorted.sort.reverse; - foreach (w; sorted) { - w.drawChildren(); - } - - // Draw the blank menubar line - reset the screen clipping first so - // it won't trim it out. - backend.screen.resetClipping(); - backend.screen.hLineXY(0, 0, backend.screen.getWidth(), ' ', - theme.getColor("tmenu")); - // Now draw the menus. - int x = 1; - foreach (m; menus) { - CellAttributes menuColor; - CellAttributes menuMnemonicColor; - if (m.active) { - menuColor = theme.getColor("tmenu.highlighted"); - menuMnemonicColor = theme.getColor("tmenu.mnemonic.highlighted"); - } else { - menuColor = theme.getColor("tmenu"); - menuMnemonicColor = theme.getColor("tmenu.mnemonic"); - } - // Draw the menu title - backend.screen.hLineXY(x, 0, cast(int)m.title.length + 2, ' ', - menuColor); - backend.screen.putStrXY(x + 1, 0, m.title, menuColor); - // Draw the highlight character - backend.screen.putCharXY(x + 1 + m.mnemonic.shortcutIdx, 0, - m.mnemonic.shortcut, menuMnemonicColor); - - if (m.active) { - m.drawChildren(); - // Reset the screen clipping so we can draw the next title. - backend.screen.resetClipping(); - } - x += m.title.length + 2; - } - - foreach (m; subMenus) { - // Reset the screen clipping so we can draw the next sub-menu. - backend.screen.resetClipping(); - m.drawChildren(); - } - */ - - // Draw the mouse pointer - drawMouse(); - - /* - // Place the cursor if it is visible - TWidget activeWidget = null; - if (sorted.length > 0) { - activeWidget = sorted[$ - 1].getActiveChild(); - if (activeWidget.hasCursor) { - backend.screen.putCursor(true, activeWidget.getCursorAbsoluteX(), - activeWidget.getCursorAbsoluteY()); - cursor = true; - } - } - - // Kill the cursor - if (cursor == false) { - backend.screen.hideCursor(); - } - */ - - // Flush the screen contents - backend.flushScreen(); - - repaint = false; - flush = false; + public final void drawAll() { + if ((flush) && (!repaint)) { + backend.flushScreen(); + flush = false; + return; + } + + if (!repaint) { + return; + } + + // If true, the cursor is not visible + boolean cursor = false; + + // Start with a clean screen + backend.getScreen().clear(); + + // Draw the background + CellAttributes background = theme.getColor("tapplication.background"); + backend.getScreen().putAll(GraphicsChars.HATCH, background); + + /* + // Draw each window in reverse Z order + TWindow [] sorted = windows.dup; + sorted.sort.reverse; + foreach (w; sorted) { + w.drawChildren(); + } + + // Draw the blank menubar line - reset the screen clipping first so + // it won't trim it out. + backend.getScreen().resetClipping(); + backend.getScreen().hLineXY(0, 0, backend.getScreen().getWidth(), ' ', + theme.getColor("tmenu")); + // Now draw the menus. + int x = 1; + foreach (m; menus) { + CellAttributes menuColor; + CellAttributes menuMnemonicColor; + if (m.active) { + menuColor = theme.getColor("tmenu.highlighted"); + menuMnemonicColor = theme.getColor("tmenu.mnemonic.highlighted"); + } else { + menuColor = theme.getColor("tmenu"); + menuMnemonicColor = theme.getColor("tmenu.mnemonic"); + } + // Draw the menu title + backend.getScreen().hLineXY(x, 0, cast(int)m.title.length + 2, ' ', + menuColor); + backend.getScreen().putStrXY(x + 1, 0, m.title, menuColor); + // Draw the highlight character + backend.getScreen().putCharXY(x + 1 + m.mnemonic.shortcutIdx, 0, + m.mnemonic.shortcut, menuMnemonicColor); + + if (m.active) { + m.drawChildren(); + // Reset the screen clipping so we can draw the next title. + backend.getScreen().resetClipping(); + } + x += m.title.length + 2; + } + + foreach (m; subMenus) { + // Reset the screen clipping so we can draw the next sub-menu. + backend.getScreen().resetClipping(); + m.drawChildren(); + } + */ + + // Draw the mouse pointer + drawMouse(); + + /* + // Place the cursor if it is visible + TWidget activeWidget = null; + if (sorted.length > 0) { + activeWidget = sorted[$ - 1].getActiveChild(); + if (activeWidget.hasCursor) { + backend.getScreen().putCursor(true, activeWidget.getCursorAbsoluteX(), + activeWidget.getCursorAbsoluteY()); + cursor = true; + } + } + + // Kill the cursor + if (cursor == false) { + backend.getScreen().hideCursor(); + } + */ + + // Flush the screen contents + backend.flushScreen(); + + repaint = false; + flush = false; } /** - * Run this application until it exits, using stdin and stdout + * Run this application until it exits. */ public final void run() { - List events = new LinkedList(); - - while (quit == false) { - // Timeout is in milliseconds, so default timeout after 1 second - // of inactivity. - int timeout = getSleepTime(1000); - - if (eventQueue.size() > 0) { - // Do not wait if there are definitely events waiting to be - // processed or a screen redraw to do. - timeout = 0; - } - - // Pull any pending input events - backend.getEvents(events, timeout); - metaHandleEvents(events); - events.clear(); - - // Process timers and call doIdle()'s - doIdle(); - - // Update the screen - drawAll(); - } - - /* - - // Shutdown the fibers - eventQueue.length = 0; - if (secondaryEventFiber !is null) { - assert(secondaryEventReceiver !is null); - secondaryEventReceiver = null; - if (secondaryEventFiber.state == Fiber.State.HOLD) { - // Wake up the secondary handler so that it can exit. - secondaryEventFiber.call(); - } - } - - if (primaryEventFiber.state == Fiber.State.HOLD) { - // Wake up the primary handler so that it can exit. - primaryEventFiber.call(); - } - */ - - backend.shutdown(); + List events = new LinkedList(); + + while (!quit) { + // Timeout is in milliseconds, so default timeout after 1 second + // of inactivity. + int timeout = getSleepTime(1000); + + if (eventQueue.size() > 0) { + // Do not wait if there are definitely events waiting to be + // processed or a screen redraw to do. + timeout = 0; + } + + // Pull any pending input events + backend.getEvents(events, timeout); + metaHandleEvents(events); + events.clear(); + + // Process timers and call doIdle()'s + doIdle(); + + // Update the screen + drawAll(); + } + + /* + + // Shutdown the fibers + eventQueue.length = 0; + if (secondaryEventFiber !is null) { + assert(secondaryEventReceiver !is null); + secondaryEventReceiver = null; + if (secondaryEventFiber.state == Fiber.State.HOLD) { + // Wake up the secondary handler so that it can exit. + secondaryEventFiber.call(); + } + } + + if (primaryEventFiber.state == Fiber.State.HOLD) { + // Wake up the primary handler so that it can exit. + primaryEventFiber.call(); + } + */ + + backend.shutdown(); } /** @@ -302,84 +314,85 @@ public class TApplication { * * @param events the input events to consume */ - private void metaHandleEvents(List events) { - - for (TInputEvent event: events) { - - /* - System.err.printf(String.format("metaHandleEvents event: %s\n", - event)); System.err.flush(); - */ - - if (quit == true) { - // Do no more processing if the application is already trying - // to exit. - return; - } - - // DEBUG - if (event instanceof TKeypressEvent) { - TKeypressEvent keypress = (TKeypressEvent)event; - if (keypress.key.equals(kbAltX)) { - quit = true; - return; - } - } - // DEBUG - - // Special application-wide events ------------------------------- - - // Abort everything - if (event instanceof TCommandEvent) { - TCommandEvent command = (TCommandEvent)event; - if (command.cmd.equals(cmAbort)) { - quit = true; - return; - } - } - - // Screen resize - if (event instanceof TResizeEvent) { - TResizeEvent resize = (TResizeEvent)event; - backend.screen.setDimensions(resize.width, resize.height); - desktopBottom = backend.screen.getHeight() - 1; - repaint = true; - mouseX = 0; - mouseY = 0; - continue; - } - - // Peek at the mouse position - if (event instanceof TMouseEvent) { - TMouseEvent mouse = (TMouseEvent)event; - if ((mouseX != mouse.x) || (mouseY != mouse.y)) { - mouseX = mouse.x; - mouseY = mouse.y; - drawMouse(); - } - } - - /* - - // Put into the main queue - addEvent(event); - - // Have one of the two consumer Fibers peel the events off - // the queue. - if (secondaryEventFiber !is null) { - assert(secondaryEventFiber.state == Fiber.State.HOLD); - - // Wake up the secondary handler for these events - secondaryEventFiber.call(); - } else { - assert(primaryEventFiber.state == Fiber.State.HOLD); - - // Wake up the primary handler for these events - primaryEventFiber.call(); - } - */ - - } // for (TInputEvent event: events) + private void metaHandleEvents(final List events) { + + for (TInputEvent event: events) { + + /* + System.err.printf(String.format("metaHandleEvents event: %s\n", + event)); System.err.flush(); + */ + + if (quit) { + // Do no more processing if the application is already trying + // to exit. + return; + } + + // DEBUG + if (event instanceof TKeypressEvent) { + TKeypressEvent keypress = (TKeypressEvent) event; + if (keypress.key.equals(kbAltX)) { + quit = true; + return; + } + } + // DEBUG + + // Special application-wide events ------------------------------- + + // Abort everything + if (event instanceof TCommandEvent) { + TCommandEvent command = (TCommandEvent) event; + if (command.getCmd().equals(cmAbort)) { + quit = true; + return; + } + } + + // Screen resize + if (event instanceof TResizeEvent) { + TResizeEvent resize = (TResizeEvent) event; + backend.getScreen().setDimensions(resize.getWidth(), + resize.getHeight()); + desktopBottom = backend.getScreen().getHeight() - 1; + repaint = true; + mouseX = 0; + mouseY = 0; + continue; + } + + // Peek at the mouse position + if (event instanceof TMouseEvent) { + TMouseEvent mouse = (TMouseEvent) event; + if ((mouseX != mouse.x) || (mouseY != mouse.y)) { + mouseX = mouse.x; + mouseY = mouse.y; + drawMouse(); + } + } + + /* + + // Put into the main queue + addEvent(event); + + // Have one of the two consumer Fibers peel the events off + // the queue. + if (secondaryEventFiber !is null) { + assert(secondaryEventFiber.state == Fiber.State.HOLD); + + // Wake up the secondary handler for these events + secondaryEventFiber.call(); + } else { + assert(primaryEventFiber.state == Fiber.State.HOLD); + + // Wake up the primary handler for these events + primaryEventFiber.call(); + } + */ + + } // for (TInputEvent event: events) } @@ -387,27 +400,27 @@ public class TApplication { * Do stuff when there is no user input. */ private void doIdle() { - /* - // Now run any timers that have timed out - auto now = Clock.currTime; - TTimer [] keepTimers; - foreach (t; timers) { - if (t.nextTick < now) { - t.tick(); - if (t.recurring == true) { - keepTimers ~= t; - } - } else { - keepTimers ~= t; - } - } - timers = keepTimers; - - // Call onIdle's - foreach (w; windows) { - w.onIdle(); - } - */ + /* + // Now run any timers that have timed out + auto now = Clock.currTime; + TTimer [] keepTimers; + foreach (t; timers) { + if (t.nextTick < now) { + t.tick(); + if (t.recurring == true) { + keepTimers ~= t; + } + } else { + keepTimers ~= t; + } + } + timers = keepTimers; + + // Call onIdle's + foreach (w; windows) { + w.onIdle(); + } + */ } /** @@ -416,25 +429,25 @@ public class TApplication { * @param timeout = initial (maximum) timeout * @return number of milliseconds between now and the next timer event */ - protected int getSleepTime(int timeout) { - /* - auto now = Clock.currTime; - auto sleepTime = dur!("msecs")(timeout); - foreach (t; timers) { - if (t.nextTick < now) { - return 0; - } - if ((t.nextTick > now) && - ((t.nextTick - now) < sleepTime) - ) { - sleepTime = t.nextTick - now; - } - } - assert(sleepTime.total!("msecs")() >= 0); - return cast(uint)sleepTime.total!("msecs")(); - */ - // TODO: fix timers. Until then, come back after 250 millis. - return 250; + protected int getSleepTime(final int timeout) { + /* + auto now = Clock.currTime; + auto sleepTime = dur!("msecs")(timeout); + foreach (t; timers) { + if (t.nextTick < now) { + return 0; + } + if ((t.nextTick > now) && + ((t.nextTick - now) < sleepTime) + ) { + sleepTime = t.nextTick - now; + } + } + assert(sleepTime.total!("msecs")() >= 0); + return cast(uint)sleepTime.total!("msecs")(); + */ + // TODO: fix timers. Until then, come back after 250 millis. + return 250; } } diff --git a/src/jexer/TCommand.java b/src/jexer/TCommand.java index ce19e2a..c51e570 100644 --- a/src/jexer/TCommand.java +++ b/src/jexer/TCommand.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,150 +24,165 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer; /** - * This class encapsulates several kinds of user commands. A user command - * can be generated by a menu action or keyboard accelerator. + * This class encapsulates a user command event. User commands can be + * generated by menu actions, keyboard accelerators, and other UI elements. + * Commands can operate on both the application and individual widgets. */ public class TCommand { + /** + * The following types are predefined for the entire system. + * + * TODO: Switch this to int so that TCommand can be subclassed so that + * applications can add more. + */ public enum Type { - /** - * Immediately abort the application (e.g. remote side closed - * connection) - */ - ABORT, - - /** - * File open dialog - */ - OPEN, - - /** - * Exit application - */ - EXIT, - - /** - * Spawn OS shell window - */ - SHELL, - - /** - * Cut selected text and copy to the clipboard - */ - CUT, - - /** - * Copy selected text to clipboard - */ - COPY, - - /** - * Paste from clipboard - */ - PASTE, - - /** - * Clear selected text without copying it to the clipboard - */ - CLEAR, - - /** - * Tile windows - */ - TILE, - - /** - * Cascade windows - */ - CASCADE, - - /** - * Close all windows - */ - CLOSE_ALL, - - /** - * Move (move/resize) window - */ - WINDOW_MOVE, - - /** - * Zoom (maximize/restore) window - */ - WINDOW_ZOOM, - - /** - * Next window (like Alt-TAB) - */ - WINDOW_NEXT, - - /** - * Previous window (like Shift-Alt-TAB) - */ - WINDOW_PREVIOUS, - - /** - * Close window - */ - WINDOW_CLOSE, + /** + * Immediately abort the application (e.g. remote side closed + * connection). + */ + ABORT, + + /** + * File open dialog. + */ + OPEN, + + /** + * Exit application. + */ + EXIT, + + /** + * Spawn OS shell window. + */ + SHELL, + + /** + * Cut selected text and copy to the clipboard. + */ + CUT, + + /** + * Copy selected text to clipboard. + */ + COPY, + + /** + * Paste from clipboard. + */ + PASTE, + + /** + * Clear selected text without copying it to the clipboard. + */ + CLEAR, + + /** + * Tile windows. + */ + TILE, + + /** + * Cascade windows. + */ + CASCADE, + + /** + * Close all windows. + */ + CLOSE_ALL, + + /** + * Move (move/resize) window. + */ + WINDOW_MOVE, + + /** + * Zoom (maximize/restore) window. + */ + WINDOW_ZOOM, + + /** + * Next window (like Alt-TAB). + */ + WINDOW_NEXT, + + /** + * Previous window (like Shift-Alt-TAB). + */ + WINDOW_PREVIOUS, + + /** + * Close window. + */ + WINDOW_CLOSE, } /** * Type of command, one of EXIT, CASCADE, etc. */ - public Type type; + private Type type; /** - * Public contructor + * Public constructor. * * @param type the Type of command, one of EXIT, CASCADE, etc. */ - public TCommand(Type type) { - this.type = type; + public TCommand(final Type type) { + this.type = type; } /** - * Make human-readable description of this event + * Make human-readable description of this TCommand. + * + * @return displayable String */ @Override - public String toString() { - return String.format("%s", type); + public final String toString() { + return String.format("%s", type); } /** - * Comparison. All fields must match to return true. + * Comparison check. All fields must match to return true. + * + * @param rhs another TCommand instance + * @return true if all fields are equal */ @Override - public boolean equals(Object rhs) { - if (!(rhs instanceof TCommand)) { - return false; - } + public final boolean equals(final Object rhs) { + if (!(rhs instanceof TCommand)) { + return false; + } - TCommand that = (TCommand)rhs; - return (type == that.type); + TCommand that = (TCommand) rhs; + return (type == that.type); } - static public final TCommand cmAbort = new TCommand(TCommand.Type.ABORT); - static public final TCommand cmExit = new TCommand(TCommand.Type.EXIT); - static public final TCommand cmQuit = new TCommand(TCommand.Type.EXIT); - static public final TCommand cmOpen = new TCommand(TCommand.Type.OPEN); - static public final TCommand cmShell = new TCommand(TCommand.Type.SHELL); - static public final TCommand cmCut = new TCommand(TCommand.Type.CUT); - static public final TCommand cmCopy = new TCommand(TCommand.Type.COPY); - static public final TCommand cmPaste = new TCommand(TCommand.Type.PASTE); - static public final TCommand cmClear = new TCommand(TCommand.Type.CLEAR); - static public final TCommand cmTile = new TCommand(TCommand.Type.TILE); - static public final TCommand cmCascade = new TCommand(TCommand.Type.CASCADE); - static public final TCommand cmCloseAll = new TCommand(TCommand.Type.CLOSE_ALL); - static public final TCommand cmWindowMove = new TCommand(TCommand.Type.WINDOW_MOVE); - static public final TCommand cmWindowZoom = new TCommand(TCommand.Type.WINDOW_ZOOM); - static public final TCommand cmWindowNext = new TCommand(TCommand.Type.WINDOW_NEXT); - static public final TCommand cmWindowPrevious = new TCommand(TCommand.Type.WINDOW_PREVIOUS); - static public final TCommand cmWindowClose = new TCommand(TCommand.Type.WINDOW_CLOSE); + public static final TCommand cmAbort = new TCommand(TCommand.Type.ABORT); + public static final TCommand cmExit = new TCommand(TCommand.Type.EXIT); + public static final TCommand cmQuit = new TCommand(TCommand.Type.EXIT); + public static final TCommand cmOpen = new TCommand(TCommand.Type.OPEN); + public static final TCommand cmShell = new TCommand(TCommand.Type.SHELL); + public static final TCommand cmCut = new TCommand(TCommand.Type.CUT); + public static final TCommand cmCopy = new TCommand(TCommand.Type.COPY); + public static final TCommand cmPaste = new TCommand(TCommand.Type.PASTE); + public static final TCommand cmClear = new TCommand(TCommand.Type.CLEAR); + public static final TCommand cmTile = new TCommand(TCommand.Type.TILE); + public static final TCommand cmCascade = new TCommand(TCommand.Type.CASCADE); + public static final TCommand cmCloseAll = new TCommand(TCommand.Type.CLOSE_ALL); + public static final TCommand cmWindowMove = new TCommand(TCommand.Type.WINDOW_MOVE); + public static final TCommand cmWindowZoom = new TCommand(TCommand.Type.WINDOW_ZOOM); + public static final TCommand cmWindowNext = new TCommand(TCommand.Type.WINDOW_NEXT); + public static final TCommand cmWindowPrevious = new TCommand(TCommand.Type.WINDOW_PREVIOUS); + public static final TCommand cmWindowClose = new TCommand(TCommand.Type.WINDOW_CLOSE); } diff --git a/src/jexer/TKeypress.java b/src/jexer/TKeypress.java index c4fd8b4..aeaadb0 100644 --- a/src/jexer/TKeypress.java +++ b/src/jexer/TKeypress.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer; @@ -40,139 +38,139 @@ public class TKeypress { // Various special keystrokes /** - * "No key" + * "No key". */ - static public final int NONE = 255; + public static final int NONE = 255; /** - * Function key F1 + * Function key F1. */ - static public final int F1 = 1; + public static final int F1 = 1; /** - * Function key F2 + * Function key F2. */ - static public final int F2 = 2; + public static final int F2 = 2; /** - * Function key F3 + * Function key F3. */ - static public final int F3 = 3; + public static final int F3 = 3; /** - * Function key F4 + * Function key F4. */ - static public final int F4 = 4; + public static final int F4 = 4; /** - * Function key F5 + * Function key F5. */ - static public final int F5 = 5; + public static final int F5 = 5; /** - * Function key F6 + * Function key F6. */ - static public final int F6 = 6; + public static final int F6 = 6; /** - * Function key F7 + * Function key F7. */ - static public final int F7 = 7; + public static final int F7 = 7; /** - * Function key F8 + * Function key F8. */ - static public final int F8 = 8; + public static final int F8 = 8; /** - * Function key F9 + * Function key F9. */ - static public final int F9 = 9; + public static final int F9 = 9; /** - * Function key F10 + * Function key F10. */ - static public final int F10 = 10; + public static final int F10 = 10; /** - * Function key F11 + * Function key F11. */ - static public final int F11 = 11; + public static final int F11 = 11; /** - * Function key F12 + * Function key F12. */ - static public final int F12 = 12; + public static final int F12 = 12; /** - * Home + * Home. */ - static public final int HOME = 20; + public static final int HOME = 20; /** - * End + * End. */ - static public final int END = 21; + public static final int END = 21; /** - * Page up + * Page up. */ - static public final int PGUP = 22; + public static final int PGUP = 22; /** - * Page down + * Page down. */ - static public final int PGDN = 23; + public static final int PGDN = 23; /** - * Insert + * Insert. */ - static public final int INS = 24; + public static final int INS = 24; /** - * Delete + * Delete. */ - static public final int DEL = 25; + public static final int DEL = 25; /** - * Right arrow + * Right arrow. */ - static public final int RIGHT = 30; + public static final int RIGHT = 30; /** - * Left arrow + * Left arrow. */ - static public final int LEFT = 31; + public static final int LEFT = 31; /** - * Up arrow + * Up arrow. */ - static public final int UP = 32; + public static final int UP = 32; /** - * Down arrow + * Down arrow. */ - static public final int DOWN = 33; + public static final int DOWN = 33; /** - * Tab + * Tab. */ - static public final int TAB = 40; + public static final int TAB = 40; /** - * Back-tab (shift-tab) + * Back-tab (shift-tab). */ - static public final int BTAB = 41; + public static final int BTAB = 41; /** - * Enter + * Enter. */ - static public final int ENTER = 42; + public static final int ENTER = 42; /** - * Escape + * Escape. */ - static public final int ESC = 43; + public static final int ESC = 43; /** * If true, ch is meaningless, use fnKey instead. @@ -185,27 +183,27 @@ public class TKeypress { public int fnKey; /** - * Keystroke modifier ALT + * Keystroke modifier ALT. */ public boolean alt; /** - * Keystroke modifier CTRL + * Keystroke modifier CTRL. */ public boolean ctrl; /** - * Keystroke modifier SHIFT + * Keystroke modifier SHIFT. */ public boolean shift; /** - * The character received + * The character received. */ public char ch; /** - * Convenience constructor for immutable instances + * Convenience constructor for the pre-defined instances. * * @param isKey is true, this is a function key * @param fnKey the function key code (only valid if isKey is true) @@ -214,203 +212,208 @@ public class TKeypress { * @param ctrl if true, CTRL was pressed with this keystroke * @param shift if true, SHIFT was pressed with this keystroke */ - public TKeypress(boolean isKey, int fnKey, char ch, - boolean alt, boolean ctrl, boolean shift) { + public TKeypress(final boolean isKey, final int fnKey, final char ch, + final boolean alt, final boolean ctrl, final boolean shift) { - this.isKey = isKey; - this.fnKey = fnKey; - this.ch = ch; - this.alt = alt; - this.ctrl = ctrl; - this.shift = shift; + this.isKey = isKey; + this.fnKey = fnKey; + this.ch = ch; + this.alt = alt; + this.ctrl = ctrl; + this.shift = shift; } /** - * Comparison. All fields must match to return true. + * Comparison check. All fields must match to return true. + * + * @param rhs another TKeypress instance + * @return true if all fields are equal */ @Override - public boolean equals(Object rhs) { - if (!(rhs instanceof TKeypress)) { - return false; - } - - TKeypress that = (TKeypress)rhs; - return ((isKey == that.isKey) && - (fnKey == that.fnKey) && - (ch == that.ch) && - (alt == that.alt) && - (ctrl == that.ctrl) && - (shift == that.shift)); + public final boolean equals(Object rhs) { + if (!(rhs instanceof TKeypress)) { + return false; + } + + TKeypress that = (TKeypress) rhs; + return ((isKey == that.isKey) + && (fnKey == that.fnKey) + && (ch == that.ch) + && (alt == that.alt) + && (ctrl == that.ctrl) + && (shift == that.shift)); } /** - * Make human-readable description of this Keystroke. + * Make human-readable description of this TKeypress. + * + * @return displayable String */ @Override - public String toString() { - if (isKey) { - switch (fnKey) { - case F1: - return String.format("%s%s%sF1", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F2: - return String.format("%s%s%sF2", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F3: - return String.format("%s%s%sF3", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F4: - return String.format("%s%s%sF4", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F5: - return String.format("%s%s%sF5", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F6: - return String.format("%s%s%sF6", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F7: - return String.format("%s%s%sF7", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F8: - return String.format("%s%s%sF8", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F9: - return String.format("%s%s%sF9", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F10: - return String.format("%s%s%sF10", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F11: - return String.format("%s%s%sF11", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case F12: - return String.format("%s%s%sF12", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case HOME: - return String.format("%s%s%sHOME", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case END: - return String.format("%s%s%sEND", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case PGUP: - return String.format("%s%s%sPGUP", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case PGDN: - return String.format("%s%s%sPGDN", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case INS: - return String.format("%s%s%sINS", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case DEL: - return String.format("%s%s%sDEL", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case RIGHT: - return String.format("%s%s%sRIGHT", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case LEFT: - return String.format("%s%s%sLEFT", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case UP: - return String.format("%s%s%sUP", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case DOWN: - return String.format("%s%s%sDOWN", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case TAB: - return String.format("%s%s%sTAB", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case BTAB: - return String.format("%s%s%sBTAB", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case ENTER: - return String.format("%s%s%sENTER", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - case ESC: - return String.format("%s%s%sESC", - ctrl ? "Ctrl+" : "", - alt ? "Alt+" : "", - shift ? "Shift+" : ""); - default: - return String.format("--UNKNOWN--"); - } - } else { - if (alt && !shift && !ctrl) { - // Alt-X - return String.format("Alt+%c", Character.toUpperCase(ch)); - } else if (!alt && shift && !ctrl) { - // Shift-X - return String.format("%c", ch); - } else if (!alt && !shift && ctrl) { - // Ctrl-X - return String.format("Ctrl+%c", ch); - } else if (alt && shift && !ctrl) { - // Alt-Shift-X - return String.format("Alt+Shift+%c", ch); - } else if (!alt && shift && ctrl) { - // Ctrl-Shift-X - return String.format("Ctrl+Shift+%c", ch); - } else if (alt && !shift && ctrl) { - // Ctrl-Alt-X - return String.format("Ctrl+Alt+%c", Character.toUpperCase(ch)); - } else if (alt && shift && ctrl) { - // Ctrl-Alt-Shift-X - return String.format("Ctrl+Alt+Shift+%c", - Character.toUpperCase(ch)); - } else { - // X - return String.format("%c", ch); - } - } + public final String toString() { + if (isKey) { + switch (fnKey) { + case F1: + return String.format("%s%s%sF1", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F2: + return String.format("%s%s%sF2", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F3: + return String.format("%s%s%sF3", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F4: + return String.format("%s%s%sF4", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F5: + return String.format("%s%s%sF5", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F6: + return String.format("%s%s%sF6", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F7: + return String.format("%s%s%sF7", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F8: + return String.format("%s%s%sF8", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F9: + return String.format("%s%s%sF9", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F10: + return String.format("%s%s%sF10", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F11: + return String.format("%s%s%sF11", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case F12: + return String.format("%s%s%sF12", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case HOME: + return String.format("%s%s%sHOME", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case END: + return String.format("%s%s%sEND", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case PGUP: + return String.format("%s%s%sPGUP", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case PGDN: + return String.format("%s%s%sPGDN", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case INS: + return String.format("%s%s%sINS", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case DEL: + return String.format("%s%s%sDEL", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case RIGHT: + return String.format("%s%s%sRIGHT", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case LEFT: + return String.format("%s%s%sLEFT", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case UP: + return String.format("%s%s%sUP", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case DOWN: + return String.format("%s%s%sDOWN", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case TAB: + return String.format("%s%s%sTAB", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case BTAB: + return String.format("%s%s%sBTAB", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case ENTER: + return String.format("%s%s%sENTER", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + case ESC: + return String.format("%s%s%sESC", + ctrl ? "Ctrl+" : "", + alt ? "Alt+" : "", + shift ? "Shift+" : ""); + default: + return String.format("--UNKNOWN--"); + } + } else { + if (alt && !shift && !ctrl) { + // Alt-X + return String.format("Alt+%c", Character.toUpperCase(ch)); + } else if (!alt && shift && !ctrl) { + // Shift-X + return String.format("%c", ch); + } else if (!alt && !shift && ctrl) { + // Ctrl-X + return String.format("Ctrl+%c", ch); + } else if (alt && shift && !ctrl) { + // Alt-Shift-X + return String.format("Alt+Shift+%c", ch); + } else if (!alt && shift && ctrl) { + // Ctrl-Shift-X + return String.format("Ctrl+Shift+%c", ch); + } else if (alt && !shift && ctrl) { + // Ctrl-Alt-X + return String.format("Ctrl+Alt+%c", Character.toUpperCase(ch)); + } else if (alt && shift && ctrl) { + // Ctrl-Alt-Shift-X + return String.format("Ctrl+Alt+Shift+%c", + Character.toUpperCase(ch)); + } else { + // X + return String.format("%c", ch); + } + } } /** @@ -420,14 +423,14 @@ public class TKeypress { * @param key keypress to convert * @return a new instance with the key converted */ - static public TKeypress toLower(TKeypress key) { - TKeypress newKey = new TKeypress(key.isKey, key.fnKey, key.ch, - key.alt, key.ctrl, key.shift); - if (!(key.isKey) && (key.ch >= 'A') && (key.ch <= 'Z') && (!key.ctrl)) { - newKey.shift = false; - newKey.ch += 32; - } - return newKey; + public static TKeypress toLower(final TKeypress key) { + TKeypress newKey = new TKeypress(key.isKey, key.fnKey, key.ch, + key.alt, key.ctrl, key.shift); + if (!(key.isKey) && (key.ch >= 'A') && (key.ch <= 'Z') && (!key.ctrl)) { + newKey.shift = false; + newKey.ch += 32; + } + return newKey; } /** @@ -437,444 +440,444 @@ public class TKeypress { * @param key keypress to convert * @return a new instance with the key converted */ - static public TKeypress toUpper(TKeypress key) { - TKeypress newKey = new TKeypress(key.isKey, key.fnKey, key.ch, - key.alt, key.ctrl, key.shift); - if (!(key.isKey) && (key.ch >= 'a') && (key.ch <= 'z') && (!key.ctrl)) { - newKey.shift = true; - newKey.ch -= 32; - } - return newKey; + public static TKeypress toUpper(final TKeypress key) { + TKeypress newKey = new TKeypress(key.isKey, key.fnKey, key.ch, + key.alt, key.ctrl, key.shift); + if (!(key.isKey) && (key.ch >= 'a') && (key.ch <= 'z') && (!key.ctrl)) { + newKey.shift = true; + newKey.ch -= 32; + } + return newKey; } // Special "no-key" keypress, used to ignore undefined keystrokes - static public final TKeypress kbNoKey = new TKeypress(true, - TKeypress.NONE, ' ', false, false, false); + public static final TKeypress kbNoKey = new TKeypress(true, + TKeypress.NONE, ' ', false, false, false); // Normal keys - static public final TKeypress kbF1 = new TKeypress(true, - TKeypress.F1, ' ', false, false, false); - static public final TKeypress kbF2 = new TKeypress(true, - TKeypress.F2, ' ', false, false, false); - static public final TKeypress kbF3 = new TKeypress(true, - TKeypress.F3, ' ', false, false, false); - static public final TKeypress kbF4 = new TKeypress(true, - TKeypress.F4, ' ', false, false, false); - static public final TKeypress kbF5 = new TKeypress(true, - TKeypress.F5, ' ', false, false, false); - static public final TKeypress kbF6 = new TKeypress(true, - TKeypress.F6, ' ', false, false, false); - static public final TKeypress kbF7 = new TKeypress(true, - TKeypress.F7, ' ', false, false, false); - static public final TKeypress kbF8 = new TKeypress(true, - TKeypress.F8, ' ', false, false, false); - static public final TKeypress kbF9 = new TKeypress(true, - TKeypress.F9, ' ', false, false, false); - static public final TKeypress kbF10 = new TKeypress(true, - TKeypress.F10, ' ', false, false, false); - static public final TKeypress kbF11 = new TKeypress(true, - TKeypress.F11, ' ', false, false, false); - static public final TKeypress kbF12 = new TKeypress(true, - TKeypress.F12, ' ', false, false, false); - static public final TKeypress kbAltF1 = new TKeypress(true, - TKeypress.F1, ' ', true, false, false); - static public final TKeypress kbAltF2 = new TKeypress(true, - TKeypress.F2, ' ', true, false, false); - static public final TKeypress kbAltF3 = new TKeypress(true, - TKeypress.F3, ' ', true, false, false); - static public final TKeypress kbAltF4 = new TKeypress(true, - TKeypress.F4, ' ', true, false, false); - static public final TKeypress kbAltF5 = new TKeypress(true, - TKeypress.F5, ' ', true, false, false); - static public final TKeypress kbAltF6 = new TKeypress(true, - TKeypress.F6, ' ', true, false, false); - static public final TKeypress kbAltF7 = new TKeypress(true, - TKeypress.F7, ' ', true, false, false); - static public final TKeypress kbAltF8 = new TKeypress(true, - TKeypress.F8, ' ', true, false, false); - static public final TKeypress kbAltF9 = new TKeypress(true, - TKeypress.F9, ' ', true, false, false); - static public final TKeypress kbAltF10 = new TKeypress(true, - TKeypress.F10, ' ', true, false, false); - static public final TKeypress kbAltF11 = new TKeypress(true, - TKeypress.F11, ' ', true, false, false); - static public final TKeypress kbAltF12 = new TKeypress(true, - TKeypress.F12, ' ', true, false, false); - static public final TKeypress kbCtrlF1 = new TKeypress(true, - TKeypress.F1, ' ', false, true, false); - static public final TKeypress kbCtrlF2 = new TKeypress(true, - TKeypress.F2, ' ', false, true, false); - static public final TKeypress kbCtrlF3 = new TKeypress(true, - TKeypress.F3, ' ', false, true, false); - static public final TKeypress kbCtrlF4 = new TKeypress(true, - TKeypress.F4, ' ', false, true, false); - static public final TKeypress kbCtrlF5 = new TKeypress(true, - TKeypress.F5, ' ', false, true, false); - static public final TKeypress kbCtrlF6 = new TKeypress(true, - TKeypress.F6, ' ', false, true, false); - static public final TKeypress kbCtrlF7 = new TKeypress(true, - TKeypress.F7, ' ', false, true, false); - static public final TKeypress kbCtrlF8 = new TKeypress(true, - TKeypress.F8, ' ', false, true, false); - static public final TKeypress kbCtrlF9 = new TKeypress(true, - TKeypress.F9, ' ', false, true, false); - static public final TKeypress kbCtrlF10 = new TKeypress(true, - TKeypress.F10, ' ', false, true, false); - static public final TKeypress kbCtrlF11 = new TKeypress(true, - TKeypress.F11, ' ', false, true, false); - static public final TKeypress kbCtrlF12 = new TKeypress(true, - TKeypress.F12, ' ', false, true, false); - static public final TKeypress kbShiftF1 = new TKeypress(true, - TKeypress.F1, ' ', false, false, true); - static public final TKeypress kbShiftF2 = new TKeypress(true, - TKeypress.F2, ' ', false, false, true); - static public final TKeypress kbShiftF3 = new TKeypress(true, - TKeypress.F3, ' ', false, false, true); - static public final TKeypress kbShiftF4 = new TKeypress(true, - TKeypress.F4, ' ', false, false, true); - static public final TKeypress kbShiftF5 = new TKeypress(true, - TKeypress.F5, ' ', false, false, true); - static public final TKeypress kbShiftF6 = new TKeypress(true, - TKeypress.F6, ' ', false, false, true); - static public final TKeypress kbShiftF7 = new TKeypress(true, - TKeypress.F7, ' ', false, false, true); - static public final TKeypress kbShiftF8 = new TKeypress(true, - TKeypress.F8, ' ', false, false, true); - static public final TKeypress kbShiftF9 = new TKeypress(true, - TKeypress.F9, ' ', false, false, true); - static public final TKeypress kbShiftF10 = new TKeypress(true, - TKeypress.F10, ' ', false, false, true); - static public final TKeypress kbShiftF11 = new TKeypress(true, - TKeypress.F11, ' ', false, false, true); - static public final TKeypress kbShiftF12 = new TKeypress(true, - TKeypress.F12, ' ', false, false, true); - static public final TKeypress kbEnter = new TKeypress(true, - TKeypress.ENTER, ' ', false, false, false); - static public final TKeypress kbTab = new TKeypress(true, - TKeypress.TAB, ' ', false, false, false); - static public final TKeypress kbEsc = new TKeypress(true, - TKeypress.ESC, ' ', false, false, false); - static public final TKeypress kbHome = new TKeypress(true, - TKeypress.HOME, ' ', false, false, false); - static public final TKeypress kbEnd = new TKeypress(true, - TKeypress.END, ' ', false, false, false); - static public final TKeypress kbPgUp = new TKeypress(true, - TKeypress.PGUP, ' ', false, false, false); - static public final TKeypress kbPgDn = new TKeypress(true, - TKeypress.PGDN, ' ', false, false, false); - static public final TKeypress kbIns = new TKeypress(true, - TKeypress.INS, ' ', false, false, false); - static public final TKeypress kbDel = new TKeypress(true, - TKeypress.DEL, ' ', false, false, false); - static public final TKeypress kbUp = new TKeypress(true, - TKeypress.UP, ' ', false, false, false); - static public final TKeypress kbDown = new TKeypress(true, - TKeypress.DOWN, ' ', false, false, false); - static public final TKeypress kbLeft = new TKeypress(true, - TKeypress.LEFT, ' ', false, false, false); - static public final TKeypress kbRight = new TKeypress(true, - TKeypress.RIGHT, ' ', false, false, false); - static public final TKeypress kbAltEnter = new TKeypress(true, - TKeypress.ENTER, ' ', true, false, false); - static public final TKeypress kbAltTab = new TKeypress(true, - TKeypress.TAB, ' ', true, false, false); - static public final TKeypress kbAltEsc = new TKeypress(true, - TKeypress.ESC, ' ', true, false, false); - static public final TKeypress kbAltHome = new TKeypress(true, - TKeypress.HOME, ' ', true, false, false); - static public final TKeypress kbAltEnd = new TKeypress(true, - TKeypress.END, ' ', true, false, false); - static public final TKeypress kbAltPgUp = new TKeypress(true, - TKeypress.PGUP, ' ', true, false, false); - static public final TKeypress kbAltPgDn = new TKeypress(true, - TKeypress.PGDN, ' ', true, false, false); - static public final TKeypress kbAltIns = new TKeypress(true, - TKeypress.INS, ' ', true, false, false); - static public final TKeypress kbAltDel = new TKeypress(true, - TKeypress.DEL, ' ', true, false, false); - static public final TKeypress kbAltUp = new TKeypress(true, - TKeypress.UP, ' ', true, false, false); - static public final TKeypress kbAltDown = new TKeypress(true, - TKeypress.DOWN, ' ', true, false, false); - static public final TKeypress kbAltLeft = new TKeypress(true, - TKeypress.LEFT, ' ', true, false, false); - static public final TKeypress kbAltRight = new TKeypress(true, - TKeypress.RIGHT, ' ', true, false, false); - static public final TKeypress kbCtrlEnter = new TKeypress(true, - TKeypress.ENTER, ' ', false, true, false); - static public final TKeypress kbCtrlTab = new TKeypress(true, - TKeypress.TAB, ' ', false, true, false); - static public final TKeypress kbCtrlEsc = new TKeypress(true, - TKeypress.ESC, ' ', false, true, false); - static public final TKeypress kbCtrlHome = new TKeypress(true, - TKeypress.HOME, ' ', false, true, false); - static public final TKeypress kbCtrlEnd = new TKeypress(true, - TKeypress.END, ' ', false, true, false); - static public final TKeypress kbCtrlPgUp = new TKeypress(true, - TKeypress.PGUP, ' ', false, true, false); - static public final TKeypress kbCtrlPgDn = new TKeypress(true, - TKeypress.PGDN, ' ', false, true, false); - static public final TKeypress kbCtrlIns = new TKeypress(true, - TKeypress.INS, ' ', false, true, false); - static public final TKeypress kbCtrlDel = new TKeypress(true, - TKeypress.DEL, ' ', false, true, false); - static public final TKeypress kbCtrlUp = new TKeypress(true, - TKeypress.UP, ' ', false, true, false); - static public final TKeypress kbCtrlDown = new TKeypress(true, - TKeypress.DOWN, ' ', false, true, false); - static public final TKeypress kbCtrlLeft = new TKeypress(true, - TKeypress.LEFT, ' ', false, true, false); - static public final TKeypress kbCtrlRight = new TKeypress(true, - TKeypress.RIGHT, ' ', false, true, false); - static public final TKeypress kbShiftEnter = new TKeypress(true, - TKeypress.ENTER, ' ', false, false, true); - static public final TKeypress kbShiftTab = new TKeypress(true, - TKeypress.TAB, ' ', false, false, true); - static public final TKeypress kbBackTab = new TKeypress(true, - TKeypress.BTAB, ' ', false, false, false); - static public final TKeypress kbShiftEsc = new TKeypress(true, - TKeypress.ESC, ' ', false, false, true); - static public final TKeypress kbShiftHome = new TKeypress(true, - TKeypress.HOME, ' ', false, false, true); - static public final TKeypress kbShiftEnd = new TKeypress(true, - TKeypress.END, ' ', false, false, true); - static public final TKeypress kbShiftPgUp = new TKeypress(true, - TKeypress.PGUP, ' ', false, false, true); - static public final TKeypress kbShiftPgDn = new TKeypress(true, - TKeypress.PGDN, ' ', false, false, true); - static public final TKeypress kbShiftIns = new TKeypress(true, - TKeypress.INS, ' ', false, false, true); - static public final TKeypress kbShiftDel = new TKeypress(true, - TKeypress.DEL, ' ', false, false, true); - static public final TKeypress kbShiftUp = new TKeypress(true, - TKeypress.UP, ' ', false, false, true); - static public final TKeypress kbShiftDown = new TKeypress(true, - TKeypress.DOWN, ' ', false, false, true); - static public final TKeypress kbShiftLeft = new TKeypress(true, - TKeypress.LEFT, ' ', false, false, true); - static public final TKeypress kbShiftRight = new TKeypress(true, - TKeypress.RIGHT, ' ', false, false, true); - static public final TKeypress kbA = new TKeypress(false, - 0, 'a', false, false, false); - static public final TKeypress kbB = new TKeypress(false, - 0, 'b', false, false, false); - static public final TKeypress kbC = new TKeypress(false, - 0, 'c', false, false, false); - static public final TKeypress kbD = new TKeypress(false, - 0, 'd', false, false, false); - static public final TKeypress kbE = new TKeypress(false, - 0, 'e', false, false, false); - static public final TKeypress kbF = new TKeypress(false, - 0, 'f', false, false, false); - static public final TKeypress kbG = new TKeypress(false, - 0, 'g', false, false, false); - static public final TKeypress kbH = new TKeypress(false, - 0, 'h', false, false, false); - static public final TKeypress kbI = new TKeypress(false, - 0, 'i', false, false, false); - static public final TKeypress kbJ = new TKeypress(false, - 0, 'j', false, false, false); - static public final TKeypress kbK = new TKeypress(false, - 0, 'k', false, false, false); - static public final TKeypress kbL = new TKeypress(false, - 0, 'l', false, false, false); - static public final TKeypress kbM = new TKeypress(false, - 0, 'm', false, false, false); - static public final TKeypress kbN = new TKeypress(false, - 0, 'n', false, false, false); - static public final TKeypress kbO = new TKeypress(false, - 0, 'o', false, false, false); - static public final TKeypress kbP = new TKeypress(false, - 0, 'p', false, false, false); - static public final TKeypress kbQ = new TKeypress(false, - 0, 'q', false, false, false); - static public final TKeypress kbR = new TKeypress(false, - 0, 'r', false, false, false); - static public final TKeypress kbS = new TKeypress(false, - 0, 's', false, false, false); - static public final TKeypress kbT = new TKeypress(false, - 0, 't', false, false, false); - static public final TKeypress kbU = new TKeypress(false, - 0, 'u', false, false, false); - static public final TKeypress kbV = new TKeypress(false, - 0, 'v', false, false, false); - static public final TKeypress kbW = new TKeypress(false, - 0, 'w', false, false, false); - static public final TKeypress kbX = new TKeypress(false, - 0, 'x', false, false, false); - static public final TKeypress kbY = new TKeypress(false, - 0, 'y', false, false, false); - static public final TKeypress kbZ = new TKeypress(false, - 0, 'z', false, false, false); - static public final TKeypress kbSpace = new TKeypress(false, - 0, ' ', false, false, false); - static public final TKeypress kbAltA = new TKeypress(false, - 0, 'a', true, false, false); - static public final TKeypress kbAltB = new TKeypress(false, - 0, 'b', true, false, false); - static public final TKeypress kbAltC = new TKeypress(false, - 0, 'c', true, false, false); - static public final TKeypress kbAltD = new TKeypress(false, - 0, 'd', true, false, false); - static public final TKeypress kbAltE = new TKeypress(false, - 0, 'e', true, false, false); - static public final TKeypress kbAltF = new TKeypress(false, - 0, 'f', true, false, false); - static public final TKeypress kbAltG = new TKeypress(false, - 0, 'g', true, false, false); - static public final TKeypress kbAltH = new TKeypress(false, - 0, 'h', true, false, false); - static public final TKeypress kbAltI = new TKeypress(false, - 0, 'i', true, false, false); - static public final TKeypress kbAltJ = new TKeypress(false, - 0, 'j', true, false, false); - static public final TKeypress kbAltK = new TKeypress(false, - 0, 'k', true, false, false); - static public final TKeypress kbAltL = new TKeypress(false, - 0, 'l', true, false, false); - static public final TKeypress kbAltM = new TKeypress(false, - 0, 'm', true, false, false); - static public final TKeypress kbAltN = new TKeypress(false, - 0, 'n', true, false, false); - static public final TKeypress kbAltO = new TKeypress(false, - 0, 'o', true, false, false); - static public final TKeypress kbAltP = new TKeypress(false, - 0, 'p', true, false, false); - static public final TKeypress kbAltQ = new TKeypress(false, - 0, 'q', true, false, false); - static public final TKeypress kbAltR = new TKeypress(false, - 0, 'r', true, false, false); - static public final TKeypress kbAltS = new TKeypress(false, - 0, 's', true, false, false); - static public final TKeypress kbAltT = new TKeypress(false, - 0, 't', true, false, false); - static public final TKeypress kbAltU = new TKeypress(false, - 0, 'u', true, false, false); - static public final TKeypress kbAltV = new TKeypress(false, - 0, 'v', true, false, false); - static public final TKeypress kbAltW = new TKeypress(false, - 0, 'w', true, false, false); - static public final TKeypress kbAltX = new TKeypress(false, - 0, 'x', true, false, false); - static public final TKeypress kbAltY = new TKeypress(false, - 0, 'y', true, false, false); - static public final TKeypress kbAltZ = new TKeypress(false, - 0, 'z', true, false, false); - static public final TKeypress kbCtrlA = new TKeypress(false, - 0, 'A', false, true, false); - static public final TKeypress kbCtrlB = new TKeypress(false, - 0, 'B', false, true, false); - static public final TKeypress kbCtrlC = new TKeypress(false, - 0, 'C', false, true, false); - static public final TKeypress kbCtrlD = new TKeypress(false, - 0, 'D', false, true, false); - static public final TKeypress kbCtrlE = new TKeypress(false, - 0, 'E', false, true, false); - static public final TKeypress kbCtrlF = new TKeypress(false, - 0, 'F', false, true, false); - static public final TKeypress kbCtrlG = new TKeypress(false, - 0, 'G', false, true, false); - static public final TKeypress kbCtrlH = new TKeypress(false, - 0, 'H', false, true, false); - static public final TKeypress kbCtrlI = new TKeypress(false, - 0, 'I', false, true, false); - static public final TKeypress kbCtrlJ = new TKeypress(false, - 0, 'J', false, true, false); - static public final TKeypress kbCtrlK = new TKeypress(false, - 0, 'K', false, true, false); - static public final TKeypress kbCtrlL = new TKeypress(false, - 0, 'L', false, true, false); - static public final TKeypress kbCtrlM = new TKeypress(false, - 0, 'M', false, true, false); - static public final TKeypress kbCtrlN = new TKeypress(false, - 0, 'N', false, true, false); - static public final TKeypress kbCtrlO = new TKeypress(false, - 0, 'O', false, true, false); - static public final TKeypress kbCtrlP = new TKeypress(false, - 0, 'P', false, true, false); - static public final TKeypress kbCtrlQ = new TKeypress(false, - 0, 'Q', false, true, false); - static public final TKeypress kbCtrlR = new TKeypress(false, - 0, 'R', false, true, false); - static public final TKeypress kbCtrlS = new TKeypress(false, - 0, 'S', false, true, false); - static public final TKeypress kbCtrlT = new TKeypress(false, - 0, 'T', false, true, false); - static public final TKeypress kbCtrlU = new TKeypress(false, - 0, 'U', false, true, false); - static public final TKeypress kbCtrlV = new TKeypress(false, - 0, 'V', false, true, false); - static public final TKeypress kbCtrlW = new TKeypress(false, - 0, 'W', false, true, false); - static public final TKeypress kbCtrlX = new TKeypress(false, - 0, 'X', false, true, false); - static public final TKeypress kbCtrlY = new TKeypress(false, - 0, 'Y', false, true, false); - static public final TKeypress kbCtrlZ = new TKeypress(false, - 0, 'Z', false, true, false); - static public final TKeypress kbAltShiftA = new TKeypress(false, - 0, 'A', true, false, true); - static public final TKeypress kbAltShiftB = new TKeypress(false, - 0, 'B', true, false, true); - static public final TKeypress kbAltShiftC = new TKeypress(false, - 0, 'C', true, false, true); - static public final TKeypress kbAltShiftD = new TKeypress(false, - 0, 'D', true, false, true); - static public final TKeypress kbAltShiftE = new TKeypress(false, - 0, 'E', true, false, true); - static public final TKeypress kbAltShiftF = new TKeypress(false, - 0, 'F', true, false, true); - static public final TKeypress kbAltShiftG = new TKeypress(false, - 0, 'G', true, false, true); - static public final TKeypress kbAltShiftH = new TKeypress(false, - 0, 'H', true, false, true); - static public final TKeypress kbAltShiftI = new TKeypress(false, - 0, 'I', true, false, true); - static public final TKeypress kbAltShiftJ = new TKeypress(false, - 0, 'J', true, false, true); - static public final TKeypress kbAltShiftK = new TKeypress(false, - 0, 'K', true, false, true); - static public final TKeypress kbAltShiftL = new TKeypress(false, - 0, 'L', true, false, true); - static public final TKeypress kbAltShiftM = new TKeypress(false, - 0, 'M', true, false, true); - static public final TKeypress kbAltShiftN = new TKeypress(false, - 0, 'N', true, false, true); - static public final TKeypress kbAltShiftO = new TKeypress(false, - 0, 'O', true, false, true); - static public final TKeypress kbAltShiftP = new TKeypress(false, - 0, 'P', true, false, true); - static public final TKeypress kbAltShiftQ = new TKeypress(false, - 0, 'Q', true, false, true); - static public final TKeypress kbAltShiftR = new TKeypress(false, - 0, 'R', true, false, true); - static public final TKeypress kbAltShiftS = new TKeypress(false, - 0, 'S', true, false, true); - static public final TKeypress kbAltShiftT = new TKeypress(false, - 0, 'T', true, false, true); - static public final TKeypress kbAltShiftU = new TKeypress(false, - 0, 'U', true, false, true); - static public final TKeypress kbAltShiftV = new TKeypress(false, - 0, 'V', true, false, true); - static public final TKeypress kbAltShiftW = new TKeypress(false, - 0, 'W', true, false, true); - static public final TKeypress kbAltShiftX = new TKeypress(false, - 0, 'X', true, false, true); - static public final TKeypress kbAltShiftY = new TKeypress(false, - 0, 'Y', true, false, true); - static public final TKeypress kbAltShiftZ = new TKeypress(false, - 0, 'Z', true, false, true); - - /** - * Backspace as ^H - */ - static public final TKeypress kbBackspace = new TKeypress(false, - 0, 'H', false, true, false); - - /** - * Backspace as ^? - */ - static public final TKeypress kbBackspaceDel = new TKeypress(false, - 0, (char)0x7F, false, false, false); + public static final TKeypress kbF1 = new TKeypress(true, + TKeypress.F1, ' ', false, false, false); + public static final TKeypress kbF2 = new TKeypress(true, + TKeypress.F2, ' ', false, false, false); + public static final TKeypress kbF3 = new TKeypress(true, + TKeypress.F3, ' ', false, false, false); + public static final TKeypress kbF4 = new TKeypress(true, + TKeypress.F4, ' ', false, false, false); + public static final TKeypress kbF5 = new TKeypress(true, + TKeypress.F5, ' ', false, false, false); + public static final TKeypress kbF6 = new TKeypress(true, + TKeypress.F6, ' ', false, false, false); + public static final TKeypress kbF7 = new TKeypress(true, + TKeypress.F7, ' ', false, false, false); + public static final TKeypress kbF8 = new TKeypress(true, + TKeypress.F8, ' ', false, false, false); + public static final TKeypress kbF9 = new TKeypress(true, + TKeypress.F9, ' ', false, false, false); + public static final TKeypress kbF10 = new TKeypress(true, + TKeypress.F10, ' ', false, false, false); + public static final TKeypress kbF11 = new TKeypress(true, + TKeypress.F11, ' ', false, false, false); + public static final TKeypress kbF12 = new TKeypress(true, + TKeypress.F12, ' ', false, false, false); + public static final TKeypress kbAltF1 = new TKeypress(true, + TKeypress.F1, ' ', true, false, false); + public static final TKeypress kbAltF2 = new TKeypress(true, + TKeypress.F2, ' ', true, false, false); + public static final TKeypress kbAltF3 = new TKeypress(true, + TKeypress.F3, ' ', true, false, false); + public static final TKeypress kbAltF4 = new TKeypress(true, + TKeypress.F4, ' ', true, false, false); + public static final TKeypress kbAltF5 = new TKeypress(true, + TKeypress.F5, ' ', true, false, false); + public static final TKeypress kbAltF6 = new TKeypress(true, + TKeypress.F6, ' ', true, false, false); + public static final TKeypress kbAltF7 = new TKeypress(true, + TKeypress.F7, ' ', true, false, false); + public static final TKeypress kbAltF8 = new TKeypress(true, + TKeypress.F8, ' ', true, false, false); + public static final TKeypress kbAltF9 = new TKeypress(true, + TKeypress.F9, ' ', true, false, false); + public static final TKeypress kbAltF10 = new TKeypress(true, + TKeypress.F10, ' ', true, false, false); + public static final TKeypress kbAltF11 = new TKeypress(true, + TKeypress.F11, ' ', true, false, false); + public static final TKeypress kbAltF12 = new TKeypress(true, + TKeypress.F12, ' ', true, false, false); + public static final TKeypress kbCtrlF1 = new TKeypress(true, + TKeypress.F1, ' ', false, true, false); + public static final TKeypress kbCtrlF2 = new TKeypress(true, + TKeypress.F2, ' ', false, true, false); + public static final TKeypress kbCtrlF3 = new TKeypress(true, + TKeypress.F3, ' ', false, true, false); + public static final TKeypress kbCtrlF4 = new TKeypress(true, + TKeypress.F4, ' ', false, true, false); + public static final TKeypress kbCtrlF5 = new TKeypress(true, + TKeypress.F5, ' ', false, true, false); + public static final TKeypress kbCtrlF6 = new TKeypress(true, + TKeypress.F6, ' ', false, true, false); + public static final TKeypress kbCtrlF7 = new TKeypress(true, + TKeypress.F7, ' ', false, true, false); + public static final TKeypress kbCtrlF8 = new TKeypress(true, + TKeypress.F8, ' ', false, true, false); + public static final TKeypress kbCtrlF9 = new TKeypress(true, + TKeypress.F9, ' ', false, true, false); + public static final TKeypress kbCtrlF10 = new TKeypress(true, + TKeypress.F10, ' ', false, true, false); + public static final TKeypress kbCtrlF11 = new TKeypress(true, + TKeypress.F11, ' ', false, true, false); + public static final TKeypress kbCtrlF12 = new TKeypress(true, + TKeypress.F12, ' ', false, true, false); + public static final TKeypress kbShiftF1 = new TKeypress(true, + TKeypress.F1, ' ', false, false, true); + public static final TKeypress kbShiftF2 = new TKeypress(true, + TKeypress.F2, ' ', false, false, true); + public static final TKeypress kbShiftF3 = new TKeypress(true, + TKeypress.F3, ' ', false, false, true); + public static final TKeypress kbShiftF4 = new TKeypress(true, + TKeypress.F4, ' ', false, false, true); + public static final TKeypress kbShiftF5 = new TKeypress(true, + TKeypress.F5, ' ', false, false, true); + public static final TKeypress kbShiftF6 = new TKeypress(true, + TKeypress.F6, ' ', false, false, true); + public static final TKeypress kbShiftF7 = new TKeypress(true, + TKeypress.F7, ' ', false, false, true); + public static final TKeypress kbShiftF8 = new TKeypress(true, + TKeypress.F8, ' ', false, false, true); + public static final TKeypress kbShiftF9 = new TKeypress(true, + TKeypress.F9, ' ', false, false, true); + public static final TKeypress kbShiftF10 = new TKeypress(true, + TKeypress.F10, ' ', false, false, true); + public static final TKeypress kbShiftF11 = new TKeypress(true, + TKeypress.F11, ' ', false, false, true); + public static final TKeypress kbShiftF12 = new TKeypress(true, + TKeypress.F12, ' ', false, false, true); + public static final TKeypress kbEnter = new TKeypress(true, + TKeypress.ENTER, ' ', false, false, false); + public static final TKeypress kbTab = new TKeypress(true, + TKeypress.TAB, ' ', false, false, false); + public static final TKeypress kbEsc = new TKeypress(true, + TKeypress.ESC, ' ', false, false, false); + public static final TKeypress kbHome = new TKeypress(true, + TKeypress.HOME, ' ', false, false, false); + public static final TKeypress kbEnd = new TKeypress(true, + TKeypress.END, ' ', false, false, false); + public static final TKeypress kbPgUp = new TKeypress(true, + TKeypress.PGUP, ' ', false, false, false); + public static final TKeypress kbPgDn = new TKeypress(true, + TKeypress.PGDN, ' ', false, false, false); + public static final TKeypress kbIns = new TKeypress(true, + TKeypress.INS, ' ', false, false, false); + public static final TKeypress kbDel = new TKeypress(true, + TKeypress.DEL, ' ', false, false, false); + public static final TKeypress kbUp = new TKeypress(true, + TKeypress.UP, ' ', false, false, false); + public static final TKeypress kbDown = new TKeypress(true, + TKeypress.DOWN, ' ', false, false, false); + public static final TKeypress kbLeft = new TKeypress(true, + TKeypress.LEFT, ' ', false, false, false); + public static final TKeypress kbRight = new TKeypress(true, + TKeypress.RIGHT, ' ', false, false, false); + public static final TKeypress kbAltEnter = new TKeypress(true, + TKeypress.ENTER, ' ', true, false, false); + public static final TKeypress kbAltTab = new TKeypress(true, + TKeypress.TAB, ' ', true, false, false); + public static final TKeypress kbAltEsc = new TKeypress(true, + TKeypress.ESC, ' ', true, false, false); + public static final TKeypress kbAltHome = new TKeypress(true, + TKeypress.HOME, ' ', true, false, false); + public static final TKeypress kbAltEnd = new TKeypress(true, + TKeypress.END, ' ', true, false, false); + public static final TKeypress kbAltPgUp = new TKeypress(true, + TKeypress.PGUP, ' ', true, false, false); + public static final TKeypress kbAltPgDn = new TKeypress(true, + TKeypress.PGDN, ' ', true, false, false); + public static final TKeypress kbAltIns = new TKeypress(true, + TKeypress.INS, ' ', true, false, false); + public static final TKeypress kbAltDel = new TKeypress(true, + TKeypress.DEL, ' ', true, false, false); + public static final TKeypress kbAltUp = new TKeypress(true, + TKeypress.UP, ' ', true, false, false); + public static final TKeypress kbAltDown = new TKeypress(true, + TKeypress.DOWN, ' ', true, false, false); + public static final TKeypress kbAltLeft = new TKeypress(true, + TKeypress.LEFT, ' ', true, false, false); + public static final TKeypress kbAltRight = new TKeypress(true, + TKeypress.RIGHT, ' ', true, false, false); + public static final TKeypress kbCtrlEnter = new TKeypress(true, + TKeypress.ENTER, ' ', false, true, false); + public static final TKeypress kbCtrlTab = new TKeypress(true, + TKeypress.TAB, ' ', false, true, false); + public static final TKeypress kbCtrlEsc = new TKeypress(true, + TKeypress.ESC, ' ', false, true, false); + public static final TKeypress kbCtrlHome = new TKeypress(true, + TKeypress.HOME, ' ', false, true, false); + public static final TKeypress kbCtrlEnd = new TKeypress(true, + TKeypress.END, ' ', false, true, false); + public static final TKeypress kbCtrlPgUp = new TKeypress(true, + TKeypress.PGUP, ' ', false, true, false); + public static final TKeypress kbCtrlPgDn = new TKeypress(true, + TKeypress.PGDN, ' ', false, true, false); + public static final TKeypress kbCtrlIns = new TKeypress(true, + TKeypress.INS, ' ', false, true, false); + public static final TKeypress kbCtrlDel = new TKeypress(true, + TKeypress.DEL, ' ', false, true, false); + public static final TKeypress kbCtrlUp = new TKeypress(true, + TKeypress.UP, ' ', false, true, false); + public static final TKeypress kbCtrlDown = new TKeypress(true, + TKeypress.DOWN, ' ', false, true, false); + public static final TKeypress kbCtrlLeft = new TKeypress(true, + TKeypress.LEFT, ' ', false, true, false); + public static final TKeypress kbCtrlRight = new TKeypress(true, + TKeypress.RIGHT, ' ', false, true, false); + public static final TKeypress kbShiftEnter = new TKeypress(true, + TKeypress.ENTER, ' ', false, false, true); + public static final TKeypress kbShiftTab = new TKeypress(true, + TKeypress.TAB, ' ', false, false, true); + public static final TKeypress kbBackTab = new TKeypress(true, + TKeypress.BTAB, ' ', false, false, false); + public static final TKeypress kbShiftEsc = new TKeypress(true, + TKeypress.ESC, ' ', false, false, true); + public static final TKeypress kbShiftHome = new TKeypress(true, + TKeypress.HOME, ' ', false, false, true); + public static final TKeypress kbShiftEnd = new TKeypress(true, + TKeypress.END, ' ', false, false, true); + public static final TKeypress kbShiftPgUp = new TKeypress(true, + TKeypress.PGUP, ' ', false, false, true); + public static final TKeypress kbShiftPgDn = new TKeypress(true, + TKeypress.PGDN, ' ', false, false, true); + public static final TKeypress kbShiftIns = new TKeypress(true, + TKeypress.INS, ' ', false, false, true); + public static final TKeypress kbShiftDel = new TKeypress(true, + TKeypress.DEL, ' ', false, false, true); + public static final TKeypress kbShiftUp = new TKeypress(true, + TKeypress.UP, ' ', false, false, true); + public static final TKeypress kbShiftDown = new TKeypress(true, + TKeypress.DOWN, ' ', false, false, true); + public static final TKeypress kbShiftLeft = new TKeypress(true, + TKeypress.LEFT, ' ', false, false, true); + public static final TKeypress kbShiftRight = new TKeypress(true, + TKeypress.RIGHT, ' ', false, false, true); + public static final TKeypress kbA = new TKeypress(false, + 0, 'a', false, false, false); + public static final TKeypress kbB = new TKeypress(false, + 0, 'b', false, false, false); + public static final TKeypress kbC = new TKeypress(false, + 0, 'c', false, false, false); + public static final TKeypress kbD = new TKeypress(false, + 0, 'd', false, false, false); + public static final TKeypress kbE = new TKeypress(false, + 0, 'e', false, false, false); + public static final TKeypress kbF = new TKeypress(false, + 0, 'f', false, false, false); + public static final TKeypress kbG = new TKeypress(false, + 0, 'g', false, false, false); + public static final TKeypress kbH = new TKeypress(false, + 0, 'h', false, false, false); + public static final TKeypress kbI = new TKeypress(false, + 0, 'i', false, false, false); + public static final TKeypress kbJ = new TKeypress(false, + 0, 'j', false, false, false); + public static final TKeypress kbK = new TKeypress(false, + 0, 'k', false, false, false); + public static final TKeypress kbL = new TKeypress(false, + 0, 'l', false, false, false); + public static final TKeypress kbM = new TKeypress(false, + 0, 'm', false, false, false); + public static final TKeypress kbN = new TKeypress(false, + 0, 'n', false, false, false); + public static final TKeypress kbO = new TKeypress(false, + 0, 'o', false, false, false); + public static final TKeypress kbP = new TKeypress(false, + 0, 'p', false, false, false); + public static final TKeypress kbQ = new TKeypress(false, + 0, 'q', false, false, false); + public static final TKeypress kbR = new TKeypress(false, + 0, 'r', false, false, false); + public static final TKeypress kbS = new TKeypress(false, + 0, 's', false, false, false); + public static final TKeypress kbT = new TKeypress(false, + 0, 't', false, false, false); + public static final TKeypress kbU = new TKeypress(false, + 0, 'u', false, false, false); + public static final TKeypress kbV = new TKeypress(false, + 0, 'v', false, false, false); + public static final TKeypress kbW = new TKeypress(false, + 0, 'w', false, false, false); + public static final TKeypress kbX = new TKeypress(false, + 0, 'x', false, false, false); + public static final TKeypress kbY = new TKeypress(false, + 0, 'y', false, false, false); + public static final TKeypress kbZ = new TKeypress(false, + 0, 'z', false, false, false); + public static final TKeypress kbSpace = new TKeypress(false, + 0, ' ', false, false, false); + public static final TKeypress kbAltA = new TKeypress(false, + 0, 'a', true, false, false); + public static final TKeypress kbAltB = new TKeypress(false, + 0, 'b', true, false, false); + public static final TKeypress kbAltC = new TKeypress(false, + 0, 'c', true, false, false); + public static final TKeypress kbAltD = new TKeypress(false, + 0, 'd', true, false, false); + public static final TKeypress kbAltE = new TKeypress(false, + 0, 'e', true, false, false); + public static final TKeypress kbAltF = new TKeypress(false, + 0, 'f', true, false, false); + public static final TKeypress kbAltG = new TKeypress(false, + 0, 'g', true, false, false); + public static final TKeypress kbAltH = new TKeypress(false, + 0, 'h', true, false, false); + public static final TKeypress kbAltI = new TKeypress(false, + 0, 'i', true, false, false); + public static final TKeypress kbAltJ = new TKeypress(false, + 0, 'j', true, false, false); + public static final TKeypress kbAltK = new TKeypress(false, + 0, 'k', true, false, false); + public static final TKeypress kbAltL = new TKeypress(false, + 0, 'l', true, false, false); + public static final TKeypress kbAltM = new TKeypress(false, + 0, 'm', true, false, false); + public static final TKeypress kbAltN = new TKeypress(false, + 0, 'n', true, false, false); + public static final TKeypress kbAltO = new TKeypress(false, + 0, 'o', true, false, false); + public static final TKeypress kbAltP = new TKeypress(false, + 0, 'p', true, false, false); + public static final TKeypress kbAltQ = new TKeypress(false, + 0, 'q', true, false, false); + public static final TKeypress kbAltR = new TKeypress(false, + 0, 'r', true, false, false); + public static final TKeypress kbAltS = new TKeypress(false, + 0, 's', true, false, false); + public static final TKeypress kbAltT = new TKeypress(false, + 0, 't', true, false, false); + public static final TKeypress kbAltU = new TKeypress(false, + 0, 'u', true, false, false); + public static final TKeypress kbAltV = new TKeypress(false, + 0, 'v', true, false, false); + public static final TKeypress kbAltW = new TKeypress(false, + 0, 'w', true, false, false); + public static final TKeypress kbAltX = new TKeypress(false, + 0, 'x', true, false, false); + public static final TKeypress kbAltY = new TKeypress(false, + 0, 'y', true, false, false); + public static final TKeypress kbAltZ = new TKeypress(false, + 0, 'z', true, false, false); + public static final TKeypress kbCtrlA = new TKeypress(false, + 0, 'A', false, true, false); + public static final TKeypress kbCtrlB = new TKeypress(false, + 0, 'B', false, true, false); + public static final TKeypress kbCtrlC = new TKeypress(false, + 0, 'C', false, true, false); + public static final TKeypress kbCtrlD = new TKeypress(false, + 0, 'D', false, true, false); + public static final TKeypress kbCtrlE = new TKeypress(false, + 0, 'E', false, true, false); + public static final TKeypress kbCtrlF = new TKeypress(false, + 0, 'F', false, true, false); + public static final TKeypress kbCtrlG = new TKeypress(false, + 0, 'G', false, true, false); + public static final TKeypress kbCtrlH = new TKeypress(false, + 0, 'H', false, true, false); + public static final TKeypress kbCtrlI = new TKeypress(false, + 0, 'I', false, true, false); + public static final TKeypress kbCtrlJ = new TKeypress(false, + 0, 'J', false, true, false); + public static final TKeypress kbCtrlK = new TKeypress(false, + 0, 'K', false, true, false); + public static final TKeypress kbCtrlL = new TKeypress(false, + 0, 'L', false, true, false); + public static final TKeypress kbCtrlM = new TKeypress(false, + 0, 'M', false, true, false); + public static final TKeypress kbCtrlN = new TKeypress(false, + 0, 'N', false, true, false); + public static final TKeypress kbCtrlO = new TKeypress(false, + 0, 'O', false, true, false); + public static final TKeypress kbCtrlP = new TKeypress(false, + 0, 'P', false, true, false); + public static final TKeypress kbCtrlQ = new TKeypress(false, + 0, 'Q', false, true, false); + public static final TKeypress kbCtrlR = new TKeypress(false, + 0, 'R', false, true, false); + public static final TKeypress kbCtrlS = new TKeypress(false, + 0, 'S', false, true, false); + public static final TKeypress kbCtrlT = new TKeypress(false, + 0, 'T', false, true, false); + public static final TKeypress kbCtrlU = new TKeypress(false, + 0, 'U', false, true, false); + public static final TKeypress kbCtrlV = new TKeypress(false, + 0, 'V', false, true, false); + public static final TKeypress kbCtrlW = new TKeypress(false, + 0, 'W', false, true, false); + public static final TKeypress kbCtrlX = new TKeypress(false, + 0, 'X', false, true, false); + public static final TKeypress kbCtrlY = new TKeypress(false, + 0, 'Y', false, true, false); + public static final TKeypress kbCtrlZ = new TKeypress(false, + 0, 'Z', false, true, false); + public static final TKeypress kbAltShiftA = new TKeypress(false, + 0, 'A', true, false, true); + public static final TKeypress kbAltShiftB = new TKeypress(false, + 0, 'B', true, false, true); + public static final TKeypress kbAltShiftC = new TKeypress(false, + 0, 'C', true, false, true); + public static final TKeypress kbAltShiftD = new TKeypress(false, + 0, 'D', true, false, true); + public static final TKeypress kbAltShiftE = new TKeypress(false, + 0, 'E', true, false, true); + public static final TKeypress kbAltShiftF = new TKeypress(false, + 0, 'F', true, false, true); + public static final TKeypress kbAltShiftG = new TKeypress(false, + 0, 'G', true, false, true); + public static final TKeypress kbAltShiftH = new TKeypress(false, + 0, 'H', true, false, true); + public static final TKeypress kbAltShiftI = new TKeypress(false, + 0, 'I', true, false, true); + public static final TKeypress kbAltShiftJ = new TKeypress(false, + 0, 'J', true, false, true); + public static final TKeypress kbAltShiftK = new TKeypress(false, + 0, 'K', true, false, true); + public static final TKeypress kbAltShiftL = new TKeypress(false, + 0, 'L', true, false, true); + public static final TKeypress kbAltShiftM = new TKeypress(false, + 0, 'M', true, false, true); + public static final TKeypress kbAltShiftN = new TKeypress(false, + 0, 'N', true, false, true); + public static final TKeypress kbAltShiftO = new TKeypress(false, + 0, 'O', true, false, true); + public static final TKeypress kbAltShiftP = new TKeypress(false, + 0, 'P', true, false, true); + public static final TKeypress kbAltShiftQ = new TKeypress(false, + 0, 'Q', true, false, true); + public static final TKeypress kbAltShiftR = new TKeypress(false, + 0, 'R', true, false, true); + public static final TKeypress kbAltShiftS = new TKeypress(false, + 0, 'S', true, false, true); + public static final TKeypress kbAltShiftT = new TKeypress(false, + 0, 'T', true, false, true); + public static final TKeypress kbAltShiftU = new TKeypress(false, + 0, 'U', true, false, true); + public static final TKeypress kbAltShiftV = new TKeypress(false, + 0, 'V', true, false, true); + public static final TKeypress kbAltShiftW = new TKeypress(false, + 0, 'W', true, false, true); + public static final TKeypress kbAltShiftX = new TKeypress(false, + 0, 'X', true, false, true); + public static final TKeypress kbAltShiftY = new TKeypress(false, + 0, 'Y', true, false, true); + public static final TKeypress kbAltShiftZ = new TKeypress(false, + 0, 'Z', true, false, true); + + /** + * Backspace as ^H. + */ + public static final TKeypress kbBackspace = new TKeypress(false, + 0, 'H', false, true, false); + + /** + * Backspace as ^?. + */ + public static final TKeypress kbBackspaceDel = new TKeypress(false, + 0, (char)0x7F, false, false, false); } diff --git a/src/jexer/backend/Backend.java b/src/jexer/backend/Backend.java index 256e9bb..3c1bffb 100644 --- a/src/jexer/backend/Backend.java +++ b/src/jexer/backend/Backend.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.backend; @@ -46,20 +44,38 @@ import jexer.session.SessionInfo; public abstract class Backend { /** - * The session information + * The session information. + */ + protected SessionInfo sessionInfo; + + /** + * Getter for sessionInfo. + * + * @return the SessionInfo + */ + public final SessionInfo getSessionInfo() { + return sessionInfo; + } + + /** + * The screen to draw on. */ - public SessionInfo session; + protected Screen screen; /** - * The screen to draw on + * Getter for screen. + * + * @return the Screen */ - public Screen screen; + public final Screen getScreen() { + return screen; + } /** * Subclasses must provide an implementation that syncs the logical * screen to the physical device. */ - abstract public void flushScreen(); + public abstract void flushScreen(); /** * Subclasses must provide an implementation to get keyboard, mouse, and @@ -69,13 +85,12 @@ public abstract class Backend { * @param timeout maximum amount of time (in millis) to wait for an * event. 0 means to return immediately, i.e. perform a poll. */ - abstract public void getEvents(List queue, int timeout); + public abstract void getEvents(List queue, int timeout); /** * Subclasses must provide an implementation that closes sockets, * restores console, etc. */ - abstract public void shutdown(); + public abstract void shutdown(); } - diff --git a/src/jexer/backend/ECMA48Backend.java b/src/jexer/backend/ECMA48Backend.java index e0ea360..a6ae361 100644 --- a/src/jexer/backend/ECMA48Backend.java +++ b/src/jexer/backend/ECMA48Backend.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.backend; @@ -62,26 +60,32 @@ public class ECMA48Backend extends Backend { * @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. + * @throws UnsupportedEncodingException if an exception is thrown when + * creating the InputStreamReader */ - public ECMA48Backend(InputStream input, OutputStream output) throws UnsupportedEncodingException { + public ECMA48Backend(final InputStream input, + final OutputStream output) throws UnsupportedEncodingException { + + // Create a terminal and explicitly set stdin into raw mode + terminal = new ECMA48Terminal(input, output); - // Create a terminal and explicitly set stdin into raw mode - terminal = new ECMA48Terminal(input, output); + // Keep the terminal's sessionInfo so that TApplication can see it + sessionInfo = terminal.getSessionInfo(); - // Create a screen - screen = new ECMA48Screen(terminal); + // Create a screen + screen = new ECMA48Screen(terminal); - // Clear the screen - terminal.getOutput().write(terminal.clearAll()); - terminal.flush(); + // Clear the screen + terminal.getOutput().write(terminal.clearAll()); + terminal.flush(); } /** * Sync the logical screen to the physical device. */ @Override - public void flushScreen() { - screen.flushPhysical(); + public final void flushScreen() { + screen.flushPhysical(); } /** @@ -92,43 +96,42 @@ public class ECMA48Backend extends Backend { * event. 0 means to return immediately, i.e. perform a poll. */ @Override - public void getEvents(List queue, int timeout) { - if (timeout > 0) { - // Try to sleep, let the terminal's input thread wake me up if - // something came in. - synchronized (terminal) { - try { - terminal.wait(timeout); - if (terminal.hasEvents()) { - // System.err.println("getEvents()"); - terminal.getEvents(queue); - } else { - // If I got here, then I timed out. Call - // terminal.getIdleEvents() to pick up stragglers - // like bare resize. - // System.err.println("getIdleEvents()"); - terminal.getIdleEvents(queue); - } - } catch (InterruptedException e) { - // Spurious interrupt, pretend it was like a timeout. - // System.err.println("[interrupt] getEvents()"); - terminal.getIdleEvents(queue); - } - } - } else { - // Asking for a poll, go get it. - System.err.println("[polled] getEvents()"); - terminal.getEvents(queue); - } + public void getEvents(final List queue, final int timeout) { + if (timeout > 0) { + // Try to sleep, let the terminal's input thread wake me up if + // something came in. + synchronized (terminal) { + try { + terminal.wait(timeout); + if (terminal.hasEvents()) { + // System.err.println("getEvents()"); + terminal.getEvents(queue); + } else { + // If I got here, then I timed out. Call + // terminal.getIdleEvents() to pick up stragglers + // like bare resize. + // System.err.println("getIdleEvents()"); + terminal.getIdleEvents(queue); + } + } catch (InterruptedException e) { + // Spurious interrupt, pretend it was like a timeout. + // System.err.println("[interrupt] getEvents()"); + terminal.getIdleEvents(queue); + } + } + } else { + // Asking for a poll, go get it. + // System.err.println("[polled] getEvents()"); + terminal.getEvents(queue); + } } /** - * Subclasses must provide an implementation that closes sockets, - * restores console, etc. + * Close the I/O, restore the console, etc. */ @Override - public void shutdown() { - terminal.shutdown(); + public final void shutdown() { + terminal.shutdown(); } } diff --git a/src/jexer/backend/package-info.java b/src/jexer/backend/package-info.java new file mode 100644 index 0000000..8c240c0 --- /dev/null +++ b/src/jexer/backend/package-info.java @@ -0,0 +1,36 @@ +/* + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * 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 + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ + +/** + * This package contains the Backend interface between TApplication and + * user-facing I/O. + */ +package jexer.backend; diff --git a/src/jexer/bits/Cell.java b/src/jexer/bits/Cell.java index 537b2a6..f110d33 100644 --- a/src/jexer/bits/Cell.java +++ b/src/jexer/bits/Cell.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,105 +24,145 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.bits; /** - * A single text cell on the screen + * This class represents a single text cell on the screen. */ public class Cell extends CellAttributes { /** - * The character at this cell + * The character at this cell. + */ + private char ch; + + /** + * Getter for cell character. + * + * @return cell character + */ + public final char getChar() { + return ch; + } + + /** + * Setter for cell character. + * + * @param ch new cell character */ - public char ch; + public final void setChar(final char ch) { + this.ch = ch; + } /** - * Reset this cell to a blank + * Reset this cell to a blank. */ @Override - public void reset() { - super.reset(); - ch = ' '; + public final void reset() { + super.reset(); + ch = ' '; } /** - * Returns true if this cell has default attributes + * Check to see if this cell has default attributes: white foreground, + * black background, no bold/blink/reverse/underline/protect, and a + * character value of ' ' (space). + * + * @return true if this cell has default attributes. */ - public boolean isBlank() { - if ((foreColor.equals(Color.WHITE)) && - (backColor.equals(Color.BLACK)) && - (bold == false) && - (blink == false) && - (reverse == false) && - (underline == false) && - (protect == false) && - (ch == ' ')) { - return true; - } + public final boolean isBlank() { + if ((getForeColor().equals(Color.WHITE)) + && (getBackColor().equals(Color.BLACK)) + && !getBold() + && !getBlink() + && !getReverse() + && !getUnderline() + && !getProtect() + && (ch == ' ') + ) { + return true; + } - return false; + return false; } /** - * Comparison. All fields must match to return true. + * Comparison check. All fields must match to return true. + * + * @param rhs another Cell instance + * @return true if all fields are equal */ @Override - public boolean equals(Object rhs) { - if (!(rhs instanceof Cell)) { - return false; - } + public final boolean equals(final Object rhs) { + if (!(rhs instanceof Cell)) { + return false; + } - Cell that = (Cell)rhs; - return (super.equals(rhs) && - (ch == that.ch)); + Cell that = (Cell) rhs; + return (super.equals(rhs) + && (ch == that.ch)); } /** - * Set my field values to that's field + * Set my field values to that's field. + * + * @param rhs an instance of either Cell or CellAttributes */ @Override - public void setTo(Object rhs) { - CellAttributes thatAttr = (CellAttributes)rhs; - super.setTo(thatAttr); + public final void setTo(final Object rhs) { + // Let this throw a ClassCastException + CellAttributes thatAttr = (CellAttributes) rhs; + super.setTo(thatAttr); - if (rhs instanceof Cell) { - Cell that = (Cell)rhs; - this.ch = that.ch; - } + if (rhs instanceof Cell) { + Cell that = (Cell) rhs; + this.ch = that.ch; + } } /** - * Set my field attr values to that's field + * Set my field attr values to that's field. + * + * @param that a CellAttributes instance */ - public void setAttr(CellAttributes that) { - super.setTo(that); + public final void setAttr(final CellAttributes that) { + super.setTo(that); } /** - * Public constructor + * Public constructor sets default values of the cell to blank. + * + * @see #isBlank() + * @see #reset() */ public Cell() { - reset(); + reset(); } /** - * Public constructor + * Public constructor sets the character. Attributes are the same as + * default. * * @param ch character to set to + * @see #reset() */ - public Cell(char ch) { - reset(); - this.ch = ch; + public Cell(final char ch) { + reset(); + this.ch = ch; } /** - * Make human-readable description of this Cell + * Make human-readable description of this Cell. + * + * @return displayable String */ @Override - public String toString() { - return String.format("fore: %d back: %d bold: %s blink: %s ch %c", - foreColor, backColor, bold, blink, ch); + public final String toString() { + return String.format("fore: %d back: %d bold: %s blink: %s ch %c", + getForeColor(), getBackColor(), getBold(), getBlink(), ch); } } - diff --git a/src/jexer/bits/CellAttributes.java b/src/jexer/bits/CellAttributes.java index 7dce699..a3d912c 100644 --- a/src/jexer/bits/CellAttributes.java +++ b/src/jexer/bits/CellAttributes.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.bits; @@ -38,164 +36,242 @@ package jexer.bits; public class CellAttributes { /** - * Bold + * Bold attribute. + */ + private boolean bold; + + /** + * Getter for bold. + * + * @return bold value + */ + public final boolean getBold() { + return bold; + } + + /** + * Setter for bold. + * + * @param bold new bold value + */ + public final void setBold(final boolean bold) { + this.bold = bold; + } + + /** + * Blink attribute. + */ + private boolean blink; + + /** + * Getter for blink. + * + * @return blink value + */ + public final boolean getBlink() { + return blink; + } + + /** + * Setter for blink. + * + * @param blink new blink value + */ + public final void setBlink(final boolean blink) { + this.blink = blink; + } + + /** + * Reverse attribute. + */ + private boolean reverse; + + /** + * Getter for reverse. + * + * @return reverse value + */ + public final boolean getReverse() { + return reverse; + } + + /** + * Setter for reverse. + * + * @param reverse new reverse value + */ + public final void setReverse(final boolean reverse) { + this.reverse = reverse; + } + + /** + * Underline attribute. */ - public boolean bold; + private boolean underline; /** - * Blink + * Getter for underline. + * + * @return underline value */ - public boolean blink; + public final boolean getUnderline() { + return underline; + } /** - * Reverse + * Setter for underline. + * + * @param underline new underline value */ - public boolean reverse; + public final void setUnderline(final boolean underline) { + this.underline = underline; + } /** - * Underline + * Protected attribute. */ - public boolean underline; + private boolean protect; /** - * Protected + * Getter for protect. + * + * @return protect value */ - public boolean protect; + public final boolean getProtect() { + return protect; + } + + /** + * Setter for protect. + * + * @param protect new protect value + */ + public final void setProtect(final boolean protect) { + this.protect = protect; + } /** * Foreground color. Color.WHITE, Color.RED, etc. */ - public Color foreColor; + private Color foreColor; + + /** + * Getter for foreColor. + * + * @return foreColor value + */ + public final Color getForeColor() { + return foreColor; + } + + /** + * Setter for foreColor. + * + * @param foreColor new foreColor value + */ + public final void setForeColor(final Color foreColor) { + this.foreColor = foreColor; + } /** * Background color. Color.WHITE, Color.RED, etc. */ - public Color backColor; + private Color backColor; + + /** + * Getter for backColor. + * + * @return backColor value + */ + public final Color getBackColor() { + return backColor; + } + + /** + * Setter for backColor. + * + * @param backColor new backColor value + */ + public final void setBackColor(final Color backColor) { + this.backColor = backColor; + } /** - * Set to default not-bold, white foreground on black background. + * Set to default: white foreground on black background, no + * bold/underline/blink/rever/protect. */ public void reset() { - bold = false; - blink = false; - reverse = false; - protect = false; - underline = false; - foreColor = Color.WHITE; - backColor = Color.BLACK; + bold = false; + blink = false; + reverse = false; + underline = false; + protect = false; + foreColor = Color.WHITE; + backColor = Color.BLACK; } /** - * Public constructor + * Public constructor sets default values of the cell to white-on-black, + * no bold/blink/reverse/underline/protect. + * + * @see #reset() */ public CellAttributes() { - reset(); + reset(); } /** - * Comparison. All fields must match to return true. + * Comparison check. All fields must match to return true. + * + * @param rhs another CellAttributes instance + * @return true if all fields are equal */ @Override - public boolean equals(Object rhs) { - if (!(rhs instanceof CellAttributes)) { - return false; - } + public boolean equals(final Object rhs) { + if (!(rhs instanceof CellAttributes)) { + return false; + } - CellAttributes that = (CellAttributes)rhs; - return ((bold == that.bold) && - (blink == that.blink) && - (reverse == that.reverse) && - (underline == that.underline) && - (protect == that.protect) && - (foreColor == that.foreColor) && - (backColor == that.backColor)); + CellAttributes that = (CellAttributes) rhs; + return ((bold == that.bold) + && (blink == that.blink) + && (reverse == that.reverse) + && (underline == that.underline) + && (protect == that.protect) + && (foreColor == that.foreColor) + && (backColor == that.backColor)); } /** - * Set my field values to that's field + * Set my field values to that's field. + * + * @param rhs another CellAttributes instance */ public void setTo(Object rhs) { - CellAttributes that = (CellAttributes)rhs; - - this.bold = that.bold; - this.blink = that.blink; - this.reverse = that.reverse; - this.underline = that.underline; - this.protect = that.protect; - this.foreColor = that.foreColor; - this.backColor = that.backColor; - } - - /** - * Convert enum to string - * - * @param color Color.RED, Color.BLUE, etc. - * @return "red", "blue", etc. - */ - static public String stringFromColor(Color color) { - if (color.equals(Color.BLACK)) { - return "black"; - } else if (color.equals(Color.WHITE)) { - return "white"; - } else if (color.equals(Color.RED)) { - return "red"; - } else if (color.equals(Color.CYAN)) { - return "cyan"; - } else if (color.equals(Color.GREEN)) { - return "green"; - } else if (color.equals(Color.MAGENTA)) { - return "magenta"; - } else if (color.equals(Color.BLUE)) { - return "blue"; - } else if (color.equals(Color.YELLOW)) { - return "yellow"; - } - throw new IllegalArgumentException("Invalid Color value: " + - color.value); - } - - /** - * Convert string to enum - * - * @param color "red", "blue", etc. - * @return Color.RED, Color.BLUE, etc. - */ - static public Color colorFromString(String color) { - switch (color.toLowerCase()) { - case "black": - return Color.BLACK; - case "white": - return Color.WHITE; - case "red": - return Color.RED; - case "cyan": - return Color.CYAN; - case "green": - return Color.GREEN; - case "magenta": - return Color.MAGENTA; - case "blue": - return Color.BLUE; - case "yellow": - return Color.YELLOW; - case "brown": - return Color.YELLOW; - default: - // Let unknown strings become white - return Color.WHITE; - } - } - - /** - * Make human-readable description of this CellAttributes + CellAttributes that = (CellAttributes) rhs; + + this.bold = that.bold; + this.blink = that.blink; + this.reverse = that.reverse; + this.underline = that.underline; + this.protect = that.protect; + this.foreColor = that.foreColor; + this.backColor = that.backColor; + } + + /** + * Make human-readable description of this CellAttributes. + * + * @return displayable String */ @Override public String toString() { - return String.format("%s%s on %s", - bold ? "bold " : "", - stringFromColor(foreColor), - stringFromColor(backColor)); + if (bold) { + return String.format("bold %s on %s", + foreColor, backColor); + } else { + return String.format("%s on %s", foreColor, backColor); + } } } - diff --git a/src/jexer/bits/Color.java b/src/jexer/bits/Color.java index dd3b93d..707b244 100644 --- a/src/jexer/bits/Color.java +++ b/src/jexer/bits/Color.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,113 +24,223 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.bits; /** * A text cell color. */ -public class Color { +public final class Color { + + /** + * The color value. Default is SGRWHITE. + */ + private int value = SGRWHITE; + + /** + * Get color value. Note that these deliberately match the color values + * of the ECMA-48 / ANSI X3.64 / VT100-ish SGR function ("ANSI colors"). + * + * @return the value + */ + public int getValue() { + return value; + } /** - * The color value. Default is WHITE. + * Private constructor used to make the static Color instances. + * + * @param value the integer Color value */ - public int value = 7; + private Color(final int value) { + this.value = value; + } /** - * Public constructor + * Public constructor returns one of the static Color instances. + * + * @param colorName "red", "blue", etc. + * @return Color.RED, Color.BLUE, etc. */ - public Color(int value) { - this.value = value; + static Color getColor(final String colorName) { + switch (colorName.toLowerCase()) { + case "black": + return Color.BLACK; + case "white": + return Color.WHITE; + case "red": + return Color.RED; + case "cyan": + return Color.CYAN; + case "green": + return Color.GREEN; + case "magenta": + return Color.MAGENTA; + case "blue": + return Color.BLUE; + case "yellow": + return Color.YELLOW; + case "brown": + return Color.YELLOW; + default: + // Let unknown strings become white + return Color.WHITE; + } } - // The color integer values. NOT EXPOSED. - static private final int black = 0; - static private final int red = 1; - static private final int green = 2; - static private final int yellow = 3; - static private final int blue = 4; - static private final int magenta = 5; - static private final int cyan = 6; - static private final int white = 7; + /** + * SGR black value = 0. + */ + private static final int SGRBLACK = 0; + + /** + * SGR red value = 1. + */ + private static final int SGRRED = 1; + + /** + * SGR green value = 2. + */ + private static final int SGRGREEN = 2; + + /** + * SGR yellow value = 3. + */ + private static final int SGRYELLOW = 3; + + /** + * SGR blue value = 4. + */ + private static final int SGRBLUE = 4; + + /** + * SGR magenta value = 5. + */ + private static final int SGRMAGENTA = 5; + + /** + * SGR cyan value = 6. + */ + private static final int SGRCYAN = 6; + + /** + * SGR white value = 7. + */ + private static final int SGRWHITE = 7; /** * Black. Bold + black = dark grey */ - static public final Color BLACK = new Color(black); + public static final Color BLACK = new Color(SGRBLACK); /** - * Red + * Red. */ - static public final Color RED = new Color(red); + public static final Color RED = new Color(SGRRED); /** - * Green + * Green. */ - static public final Color GREEN = new Color(green); + public static final Color GREEN = new Color(SGRGREEN); /** * Yellow. Sometimes not-bold yellow is brown. */ - static public final Color YELLOW = new Color(yellow); + public static final Color YELLOW = new Color(SGRYELLOW); /** - * Blue + * Blue. */ - static public final Color BLUE = new Color(blue); + public static final Color BLUE = new Color(SGRBLUE); /** - * Magenta (purple) + * Magenta (purple). */ - static public final Color MAGENTA = new Color(magenta); + public static final Color MAGENTA = new Color(SGRMAGENTA); /** - * Cyan (blue-green) + * Cyan (blue-green). */ - static public final Color CYAN = new Color(cyan); + public static final Color CYAN = new Color(SGRCYAN); /** - * White + * White. */ - static public final Color WHITE = new Color(white); + public static final Color WHITE = new Color(SGRWHITE); /** * Invert a color in the same way as (CGA/VGA color XOR 0x7). + * * @return the inverted color */ public Color invert() { - switch (value) { - case black: - return Color.WHITE; - case white: - return Color.BLACK; - case red: - return Color.CYAN; - case cyan: - return Color.RED; - case green: - return Color.MAGENTA; - case magenta: - return Color.GREEN; - case blue: - return Color.YELLOW; - case yellow: - return Color.BLUE; - } - throw new IllegalArgumentException("Invalid Color value: " + - value); + switch (value) { + case SGRBLACK: + return Color.WHITE; + case SGRWHITE: + return Color.BLACK; + case SGRRED: + return Color.CYAN; + case SGRCYAN: + return Color.RED; + case SGRGREEN: + return Color.MAGENTA; + case SGRMAGENTA: + return Color.GREEN; + case SGRBLUE: + return Color.YELLOW; + case SGRYELLOW: + return Color.BLUE; + default: + throw new IllegalArgumentException("Invalid Color value: " + value); + } } /** - * Comparison. All fields must match to return true. + * Comparison check. All fields must match to return true. + * + * @param rhs another Color instance + * @return true if all fields are equal */ @Override - public boolean equals(Object rhs) { - if (!(rhs instanceof Color)) { - return false; - } + public boolean equals(final Object rhs) { + if (!(rhs instanceof Color)) { + return false; + } + + Color that = (Color) rhs; + return (value == that.value); + } - Color that = (Color)rhs; - return (value == that.value); + /** + * Make human-readable description of this Color. + * + * @return displayable String "red", "blue", etc. + */ + @Override + public String toString() { + switch (value) { + case SGRBLACK: + return "black"; + case SGRWHITE: + return "white"; + case SGRRED: + return "red"; + case SGRCYAN: + return "cyan"; + case SGRGREEN: + return "green"; + case SGRMAGENTA: + return "magenta"; + case SGRBLUE: + return "blue"; + case SGRYELLOW: + return "yellow"; + } + throw new IllegalArgumentException("Invalid Color value: " + value); } + } diff --git a/src/jexer/bits/ColorTheme.java b/src/jexer/bits/ColorTheme.java index ff78af4..6f40699 100644 --- a/src/jexer/bits/ColorTheme.java +++ b/src/jexer/bits/ColorTheme.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.bits; @@ -41,381 +39,384 @@ import java.util.StringTokenizer; import java.util.TreeMap; /** - * ColorTheme is a collection of colors keyed by string. + * ColorTheme is a collection of colors keyed by string. A default theme is + * also provided that matches the blue-and-white theme used by Turbo Vision. */ -public class ColorTheme { +public final class ColorTheme { /** - * The current theme colors + * The current theme colors. */ private SortedMap colors; /** - * Public constructor. + * Public constructor sets the theme to the default. */ public ColorTheme() { - colors = new TreeMap(); - setDefaultTheme(); + colors = new TreeMap(); + setDefaultTheme(); } /** - * Retrieve the CellAttributes by name. + * Retrieve the CellAttributes for a named theme color. * - * @param name hash key - * @return color associated with hash key + * @param name theme color name, e.g. "twindow.border" + * @return color associated with name, e.g. bold yellow on blue */ - public CellAttributes getColor(String name) { - CellAttributes attr = (CellAttributes)colors.get(name); - return attr; + public CellAttributes getColor(final String name) { + CellAttributes attr = (CellAttributes) colors.get(name); + return attr; } /** - * Save the colors to an ASCII file + * Save the color theme mappings to an ASCII file. * * @param filename file to write to + * @throws IOException if the I/O fails */ - public void save(String filename) throws IOException { - FileWriter file = new FileWriter(filename); - for (String key: colors.keySet()) { - CellAttributes color = getColor(key); - file.write(String.format("%s = %s\n", key, color)); - } - file.close(); + public void save(final String filename) throws IOException { + FileWriter file = new FileWriter(filename); + for (String key: colors.keySet()) { + CellAttributes color = getColor(key); + file.write(String.format("%s = %s\n", key, color)); + } + file.close(); } /** - * Read colors from an ASCII file + * Read color theme mappings from an ASCII file. * * @param filename file to read from + * @throws IOException if the I/O fails */ - public void load(String filename) throws IOException { - BufferedReader reader = new BufferedReader(new FileReader(filename)); - String line = reader.readLine(); - for (; line != null; line = reader.readLine()) { - String key; - String bold; - String foreColor; - String backColor; - - // Look for lines that resemble: - // "key = blah on blah" - // "key = bold blah on blah" - StringTokenizer tokenizer = new StringTokenizer(line); - key = tokenizer.nextToken(); - if (!tokenizer.nextToken().equals("=")) { - // Skip this line - continue; - } - bold = tokenizer.nextToken(); - if (!bold.toLowerCase().equals("bold")) { - // "key = blah on blah" - foreColor = bold; - } else { - // "key = bold blah on blah" - foreColor = tokenizer.nextToken().toLowerCase(); - } - if (!tokenizer.nextToken().toLowerCase().equals("on")) { - // Skip this line - continue; - } - backColor = tokenizer.nextToken().toLowerCase(); - - CellAttributes color = new CellAttributes(); - if (bold.equals("bold")) { - color.bold = true; - } - color.foreColor = CellAttributes.colorFromString(foreColor); - color.backColor = CellAttributes.colorFromString(backColor); - colors.put(key, color); - } + public void load(final String filename) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(filename)); + String line = reader.readLine(); + for (; line != null; line = reader.readLine()) { + String key; + String bold; + String foreColor; + String backColor; + + // Look for lines that resemble: + // "key = blah on blah" + // "key = bold blah on blah" + StringTokenizer tokenizer = new StringTokenizer(line); + key = tokenizer.nextToken(); + if (!tokenizer.nextToken().equals("=")) { + // Skip this line + continue; + } + bold = tokenizer.nextToken(); + if (!bold.toLowerCase().equals("bold")) { + // "key = blah on blah" + foreColor = bold; + } else { + // "key = bold blah on blah" + foreColor = tokenizer.nextToken().toLowerCase(); + } + if (!tokenizer.nextToken().toLowerCase().equals("on")) { + // Skip this line + continue; + } + backColor = tokenizer.nextToken().toLowerCase(); + + CellAttributes color = new CellAttributes(); + if (bold.equals("bold")) { + color.setBold(true); + } + color.setForeColor(Color.getColor(foreColor)); + color.setBackColor(Color.getColor(backColor)); + colors.put(key, color); + } } /** * Sets to defaults that resemble the Borland IDE colors. */ public void setDefaultTheme() { - CellAttributes color; - - // TWindow border - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("twindow.border", color); - - // TWindow background - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("twindow.background", color); - - // TWindow border - inactive - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("twindow.border.inactive", color); - - // TWindow background - inactive - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("twindow.background.inactive", color); - - // TWindow border - modal - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.WHITE; - color.bold = true; - colors.put("twindow.border.modal", color); - - // TWindow background - modal - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.WHITE; - color.bold = false; - colors.put("twindow.background.modal", color); - - // TWindow border - modal + inactive - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.WHITE; - color.bold = true; - colors.put("twindow.border.modal.inactive", color); - - // TWindow background - modal + inactive - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.WHITE; - color.bold = false; - colors.put("twindow.background.modal.inactive", color); - - // TWindow border - during window movement - modal - color = new CellAttributes(); - color.foreColor = Color.GREEN; - color.backColor = Color.WHITE; - color.bold = true; - colors.put("twindow.border.modal.windowmove", color); - - // TWindow border - during window movement - color = new CellAttributes(); - color.foreColor = Color.GREEN; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("twindow.border.windowmove", color); - - // TWindow background - during window movement - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("twindow.background.windowmove", color); - - // TApplication background - color = new CellAttributes(); - color.foreColor = Color.BLUE; - color.backColor = Color.WHITE; - color.bold = false; - colors.put("tapplication.background", color); - - // TButton text - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.GREEN; - color.bold = false; - colors.put("tbutton.inactive", color); - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.GREEN; - color.bold = true; - colors.put("tbutton.active", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.WHITE; - color.bold = true; - colors.put("tbutton.disabled", color); - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.GREEN; - color.bold = true; - colors.put("tbutton.mnemonic", color); - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.GREEN; - color.bold = true; - colors.put("tbutton.mnemonic.highlighted", color); - - // TLabel text - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("tlabel", color); - - // TText text - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLACK; - color.bold = false; - colors.put("ttext", color); - - // TField text - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tfield.inactive", color); - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLACK; - color.bold = true; - colors.put("tfield.active", color); - - // TCheckbox - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tcheckbox.inactive", color); - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLACK; - color.bold = true; - colors.put("tcheckbox.active", color); - - - // TRadioButton - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tradiobutton.inactive", color); - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLACK; - color.bold = true; - colors.put("tradiobutton.active", color); - - // TRadioGroup - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tradiogroup.inactive", color); - color = new CellAttributes(); - color.foreColor = Color.YELLOW; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("tradiogroup.active", color); - - // TMenu - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.WHITE; - color.bold = false; - colors.put("tmenu", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.GREEN; - color.bold = false; - colors.put("tmenu.highlighted", color); - color = new CellAttributes(); - color.foreColor = Color.RED; - color.backColor = Color.WHITE; - color.bold = false; - colors.put("tmenu.mnemonic", color); - color = new CellAttributes(); - color.foreColor = Color.RED; - color.backColor = Color.GREEN; - color.bold = false; - colors.put("tmenu.mnemonic.highlighted", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.WHITE; - color.bold = true; - colors.put("tmenu.disabled", color); - - // TProgressBar - color = new CellAttributes(); - color.foreColor = Color.BLUE; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("tprogressbar.complete", color); - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tprogressbar.incomplete", color); - - // THScroller / TVScroller - color = new CellAttributes(); - color.foreColor = Color.CYAN; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tscroller.bar", color); - color = new CellAttributes(); - color.foreColor = Color.BLUE; - color.backColor = Color.CYAN; - color.bold = false; - colors.put("tscroller.arrows", color); - - // TTreeView - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("ttreeview", color); - color = new CellAttributes(); - color.foreColor = Color.GREEN; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("ttreeview.expandbutton", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.CYAN; - color.bold = false; - colors.put("ttreeview.selected", color); - color = new CellAttributes(); - color.foreColor = Color.RED; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("ttreeview.unreadable", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("ttreeview.inactive", color); - - // TText text - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLUE; - color.bold = false; - colors.put("tdirectorylist", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.CYAN; - color.bold = false; - colors.put("tdirectorylist.selected", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.CYAN; - color.bold = false; - colors.put("tdirectorylist.unreadable", color); - color = new CellAttributes(); - color.foreColor = Color.BLACK; - color.backColor = Color.BLUE; - color.bold = true; - colors.put("tdirectorylist.inactive", color); - - // TEditor - color = new CellAttributes(); - color.foreColor = Color.WHITE; - color.backColor = Color.BLACK; - color.bold = false; - colors.put("teditor", color); + CellAttributes color; + + // TWindow border + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("twindow.border", color); + + // TWindow background + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("twindow.background", color); + + // TWindow border - inactive + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("twindow.border.inactive", color); + + // TWindow background - inactive + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("twindow.background.inactive", color); + + // TWindow border - modal + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.WHITE); + color.setBold(true); + colors.put("twindow.border.modal", color); + + // TWindow background - modal + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.WHITE); + color.setBold(false); + colors.put("twindow.background.modal", color); + + // TWindow border - modal + inactive + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.WHITE); + color.setBold(true); + colors.put("twindow.border.modal.inactive", color); + + // TWindow background - modal + inactive + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.WHITE); + color.setBold(false); + colors.put("twindow.background.modal.inactive", color); + + // TWindow border - during window movement - modal + color = new CellAttributes(); + color.setForeColor(Color.GREEN); + color.setBackColor(Color.WHITE); + color.setBold(true); + colors.put("twindow.border.modal.windowmove", color); + + // TWindow border - during window movement + color = new CellAttributes(); + color.setForeColor(Color.GREEN); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("twindow.border.windowmove", color); + + // TWindow background - during window movement + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("twindow.background.windowmove", color); + + // TApplication background + color = new CellAttributes(); + color.setForeColor(Color.BLUE); + color.setBackColor(Color.WHITE); + color.setBold(false); + colors.put("tapplication.background", color); + + // TButton text + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.GREEN); + color.setBold(false); + colors.put("tbutton.inactive", color); + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.GREEN); + color.setBold(true); + colors.put("tbutton.active", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.WHITE); + color.setBold(true); + colors.put("tbutton.disabled", color); + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.GREEN); + color.setBold(true); + colors.put("tbutton.mnemonic", color); + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.GREEN); + color.setBold(true); + colors.put("tbutton.mnemonic.highlighted", color); + + // TLabel text + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("tlabel", color); + + // TText text + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLACK); + color.setBold(false); + colors.put("ttext", color); + + // TField text + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tfield.inactive", color); + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLACK); + color.setBold(true); + colors.put("tfield.active", color); + + // TCheckbox + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tcheckbox.inactive", color); + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLACK); + color.setBold(true); + colors.put("tcheckbox.active", color); + + + // TRadioButton + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tradiobutton.inactive", color); + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLACK); + color.setBold(true); + colors.put("tradiobutton.active", color); + + // TRadioGroup + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tradiogroup.inactive", color); + color = new CellAttributes(); + color.setForeColor(Color.YELLOW); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("tradiogroup.active", color); + + // TMenu + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.WHITE); + color.setBold(false); + colors.put("tmenu", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.GREEN); + color.setBold(false); + colors.put("tmenu.highlighted", color); + color = new CellAttributes(); + color.setForeColor(Color.RED); + color.setBackColor(Color.WHITE); + color.setBold(false); + colors.put("tmenu.mnemonic", color); + color = new CellAttributes(); + color.setForeColor(Color.RED); + color.setBackColor(Color.GREEN); + color.setBold(false); + colors.put("tmenu.mnemonic.highlighted", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.WHITE); + color.setBold(true); + colors.put("tmenu.disabled", color); + + // TProgressBar + color = new CellAttributes(); + color.setForeColor(Color.BLUE); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("tprogressbar.complete", color); + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tprogressbar.incomplete", color); + + // THScroller / TVScroller + color = new CellAttributes(); + color.setForeColor(Color.CYAN); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tscroller.bar", color); + color = new CellAttributes(); + color.setForeColor(Color.BLUE); + color.setBackColor(Color.CYAN); + color.setBold(false); + colors.put("tscroller.arrows", color); + + // TTreeView + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("ttreeview", color); + color = new CellAttributes(); + color.setForeColor(Color.GREEN); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("ttreeview.expandbutton", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.CYAN); + color.setBold(false); + colors.put("ttreeview.selected", color); + color = new CellAttributes(); + color.setForeColor(Color.RED); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("ttreeview.unreadable", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("ttreeview.inactive", color); + + // TText text + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLUE); + color.setBold(false); + colors.put("tdirectorylist", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.CYAN); + color.setBold(false); + colors.put("tdirectorylist.selected", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.CYAN); + color.setBold(false); + colors.put("tdirectorylist.unreadable", color); + color = new CellAttributes(); + color.setForeColor(Color.BLACK); + color.setBackColor(Color.BLUE); + color.setBold(true); + colors.put("tdirectorylist.inactive", color); + + // TEditor + color = new CellAttributes(); + color.setForeColor(Color.WHITE); + color.setBackColor(Color.BLACK); + color.setBold(false); + colors.put("teditor", color); } diff --git a/src/jexer/bits/GraphicsChars.java b/src/jexer/bits/GraphicsChars.java index 1929631..747e757 100644 --- a/src/jexer/bits/GraphicsChars.java +++ b/src/jexer/bits/GraphicsChars.java @@ -1,16 +1,11 @@ /** - * Jexer - Java Text User Interface - code pages - * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com + * Jexer - Java Text User Interface * * 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. + * 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 * @@ -29,86 +24,124 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.bits; /** - * Collection of special characters used by the windowing system. + * This class contains a collection of special characters used by the + * windowing system and the mappings from CP437 to Unicode. */ -public class GraphicsChars { +public final class GraphicsChars { /** - * CP437 translation map + * Private constructor prevents accidental creation of this class. */ - static private final char cp437_chars[] = { - - '\u2007', '\u263A', '\u263B', '\u2665', '\u2666', '\u2663', '\u2660', '\u2022', - '\u25D8', '\u25CB', '\u25D9', '\u2642', '\u2640', '\u266A', '\u266B', '\u263C', - '\u25BA', '\u25C4', '\u2195', '\u203C', '\u00B6', '\u00A7', '\u25AC', '\u21A8', - '\u2191', '\u2193', '\u2192', '\u2190', '\u221F', '\u2194', '\u25B2', '\u25BC', - '\u0020', '\u0021', '\"', '\u0023', '\u0024', '\u0025', '\u0026', '\'', + private GraphicsChars() { + } - '\u0028', '\u0029', '\u002a', '\u002b', '\u002c', '\u002d', '\u002e', '\u002f', - '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', - '\u0038', '\u0039', '\u003a', '\u003b', '\u003c', '\u003d', '\u003e', '\u003f', - '\u0040', '\u0041', '\u0042', '\u0043', '\u0044', '\u0045', '\u0046', '\u0047', - '\u0048', '\u0049', '\u004a', '\u004b', '\u004c', '\u004d', '\u004e', '\u004f', - '\u0050', '\u0051', '\u0052', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057', - '\u0058', '\u0059', '\u005a', '\u005b', '\\', '\u005d', '\u005e', '\u005f', - '\u0060', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066', '\u0067', - '\u0068', '\u0069', '\u006a', '\u006b', '\u006c', '\u006d', '\u006e', '\u006f', - '\u0070', '\u0071', '\u0072', '\u0073', '\u0074', '\u0075', '\u0076', '\u0077', - '\u0078', '\u0079', '\u007a', '\u007b', '\u007c', '\u007d', '\u007e', '\u007f', - '\u00c7', '\u00fc', '\u00e9', '\u00e2', '\u00e4', '\u00e0', '\u00e5', '\u00e7', - '\u00ea', '\u00eb', '\u00e8', '\u00ef', '\u00ee', '\u00ec', '\u00c4', '\u00c5', - '\u00c9', '\u00e6', '\u00c6', '\u00f4', '\u00f6', '\u00f2', '\u00fb', '\u00f9', - '\u00ff', '\u00d6', '\u00dc', '\u00a2', '\u00a3', '\u00a5', '\u20a7', '\u0192', - '\u00e1', '\u00ed', '\u00f3', '\u00fa', '\u00f1', '\u00d1', '\u00aa', '\u00ba', - '\u00bf', '\u2310', '\u00ac', '\u00bd', '\u00bc', '\u00a1', '\u00ab', '\u00bb', - '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', - '\u2555', '\u2563', '\u2551', '\u2557', '\u255d', '\u255c', '\u255b', '\u2510', - '\u2514', '\u2534', '\u252c', '\u251c', '\u2500', '\u253c', '\u255e', '\u255f', - '\u255a', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256c', '\u2567', - '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256b', - '\u256a', '\u2518', '\u250c', '\u2588', '\u2584', '\u258c', '\u2590', '\u2580', - '\u03b1', '\u00df', '\u0393', '\u03c0', '\u03a3', '\u03c3', '\u00b5', '\u03c4', - '\u03a6', '\u0398', '\u03a9', '\u03b4', '\u221e', '\u03c6', '\u03b5', '\u2229', - '\u2261', '\u00b1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00f7', '\u2248', - '\u00b0', '\u2219', '\u00b7', '\u221a', '\u207f', '\u00b2', '\u25a0', '\u00a0' + /** + * The CP437 to Unicode translation map. + */ + private static final char [] CP437 = { + '\u2007', '\u263A', '\u263B', '\u2665', + '\u2666', '\u2663', '\u2660', '\u2022', + '\u25D8', '\u25CB', '\u25D9', '\u2642', + '\u2640', '\u266A', '\u266B', '\u263C', + '\u25BA', '\u25C4', '\u2195', '\u203C', + '\u00B6', '\u00A7', '\u25AC', '\u21A8', + '\u2191', '\u2193', '\u2192', '\u2190', + '\u221F', '\u2194', '\u25B2', '\u25BC', + '\u0020', '\u0021', '\"', '\u0023', + '\u0024', '\u0025', '\u0026', '\'', + '\u0028', '\u0029', '\u002a', '\u002b', + '\u002c', '\u002d', '\u002e', '\u002f', + '\u0030', '\u0031', '\u0032', '\u0033', + '\u0034', '\u0035', '\u0036', '\u0037', + '\u0038', '\u0039', '\u003a', '\u003b', + '\u003c', '\u003d', '\u003e', '\u003f', + '\u0040', '\u0041', '\u0042', '\u0043', + '\u0044', '\u0045', '\u0046', '\u0047', + '\u0048', '\u0049', '\u004a', '\u004b', + '\u004c', '\u004d', '\u004e', '\u004f', + '\u0050', '\u0051', '\u0052', '\u0053', + '\u0054', '\u0055', '\u0056', '\u0057', + '\u0058', '\u0059', '\u005a', '\u005b', + '\\', '\u005d', '\u005e', '\u005f', + '\u0060', '\u0061', '\u0062', '\u0063', + '\u0064', '\u0065', '\u0066', '\u0067', + '\u0068', '\u0069', '\u006a', '\u006b', + '\u006c', '\u006d', '\u006e', '\u006f', + '\u0070', '\u0071', '\u0072', '\u0073', + '\u0074', '\u0075', '\u0076', '\u0077', + '\u0078', '\u0079', '\u007a', '\u007b', + '\u007c', '\u007d', '\u007e', '\u007f', + '\u00c7', '\u00fc', '\u00e9', '\u00e2', + '\u00e4', '\u00e0', '\u00e5', '\u00e7', + '\u00ea', '\u00eb', '\u00e8', '\u00ef', + '\u00ee', '\u00ec', '\u00c4', '\u00c5', + '\u00c9', '\u00e6', '\u00c6', '\u00f4', + '\u00f6', '\u00f2', '\u00fb', '\u00f9', + '\u00ff', '\u00d6', '\u00dc', '\u00a2', + '\u00a3', '\u00a5', '\u20a7', '\u0192', + '\u00e1', '\u00ed', '\u00f3', '\u00fa', + '\u00f1', '\u00d1', '\u00aa', '\u00ba', + '\u00bf', '\u2310', '\u00ac', '\u00bd', + '\u00bc', '\u00a1', '\u00ab', '\u00bb', + '\u2591', '\u2592', '\u2593', '\u2502', + '\u2524', '\u2561', '\u2562', '\u2556', + '\u2555', '\u2563', '\u2551', '\u2557', + '\u255d', '\u255c', '\u255b', '\u2510', + '\u2514', '\u2534', '\u252c', '\u251c', + '\u2500', '\u253c', '\u255e', '\u255f', + '\u255a', '\u2554', '\u2569', '\u2566', + '\u2560', '\u2550', '\u256c', '\u2567', + '\u2568', '\u2564', '\u2565', '\u2559', + '\u2558', '\u2552', '\u2553', '\u256b', + '\u256a', '\u2518', '\u250c', '\u2588', + '\u2584', '\u258c', '\u2590', '\u2580', + '\u03b1', '\u00df', '\u0393', '\u03c0', + '\u03a3', '\u03c3', '\u00b5', '\u03c4', + '\u03a6', '\u0398', '\u03a9', '\u03b4', + '\u221e', '\u03c6', '\u03b5', '\u2229', + '\u2261', '\u00b1', '\u2265', '\u2264', + '\u2320', '\u2321', '\u00f7', '\u2248', + '\u00b0', '\u2219', '\u00b7', '\u221a', + '\u207f', '\u00b2', '\u25a0', '\u00a0' }; - - static public final char HATCH = cp437_chars[0xB0]; - static public final char DOUBLE_BAR = cp437_chars[0xCD]; - static public final char BOX = cp437_chars[0xFE]; - static public final char CHECK = cp437_chars[0xFB]; - static public final char TRIPLET = cp437_chars[0xF0]; - static public final char OMEGA = cp437_chars[0xEA]; - static public final char PI = cp437_chars[0xE3]; - static public final char UPARROW = cp437_chars[0x18]; - static public final char DOWNARROW = cp437_chars[0x19]; - static public final char RIGHTARROW = cp437_chars[0x1A]; - static public final char LEFTARROW = cp437_chars[0x1B]; - static public final char SINGLE_BAR = cp437_chars[0xC4]; - static public final char BACK_ARROWHEAD = cp437_chars[0x11]; - static public final char LRCORNER = cp437_chars[0xD9]; - static public final char URCORNER = cp437_chars[0xBF]; - static public final char LLCORNER = cp437_chars[0xC0]; - static public final char ULCORNER = cp437_chars[0xDA]; - static public final char DEGREE = cp437_chars[0xF8]; - static public final char PLUSMINUS = cp437_chars[0xF1]; - static public final char WINDOW_TOP = cp437_chars[0xCD]; - static public final char WINDOW_LEFT_TOP = cp437_chars[0xD5]; - static public final char WINDOW_RIGHT_TOP = cp437_chars[0xB8]; - static public final char WINDOW_SIDE = cp437_chars[0xB3]; - static public final char WINDOW_LEFT_BOTTOM = cp437_chars[0xD4]; - static public final char WINDOW_RIGHT_BOTTOM = cp437_chars[0xBE]; - static public final char WINDOW_LEFT_TEE = cp437_chars[0xC6]; - static public final char WINDOW_RIGHT_TEE = cp437_chars[0xB5]; - static public final char WINDOW_SIDE_DOUBLE = cp437_chars[0xBA]; - static public final char WINDOW_LEFT_TOP_DOUBLE = cp437_chars[0xC9]; - static public final char WINDOW_RIGHT_TOP_DOUBLE = cp437_chars[0xBB]; - static public final char WINDOW_LEFT_BOTTOM_DOUBLE = cp437_chars[0xC8]; - static public final char WINDOW_RIGHT_BOTTOM_DOUBLE = cp437_chars[0xBC]; + public static final char HATCH = CP437[0xB0]; + public static final char DOUBLE_BAR = CP437[0xCD]; + public static final char BOX = CP437[0xFE]; + public static final char CHECK = CP437[0xFB]; + public static final char TRIPLET = CP437[0xF0]; + public static final char OMEGA = CP437[0xEA]; + public static final char PI = CP437[0xE3]; + public static final char UPARROW = CP437[0x18]; + public static final char DOWNARROW = CP437[0x19]; + public static final char RIGHTARROW = CP437[0x1A]; + public static final char LEFTARROW = CP437[0x1B]; + public static final char SINGLE_BAR = CP437[0xC4]; + public static final char BACK_ARROWHEAD = CP437[0x11]; + public static final char LRCORNER = CP437[0xD9]; + public static final char URCORNER = CP437[0xBF]; + public static final char LLCORNER = CP437[0xC0]; + public static final char ULCORNER = CP437[0xDA]; + public static final char DEGREE = CP437[0xF8]; + public static final char PLUSMINUS = CP437[0xF1]; + public static final char WINDOW_TOP = CP437[0xCD]; + public static final char WINDOW_LEFT_TOP = CP437[0xD5]; + public static final char WINDOW_RIGHT_TOP = CP437[0xB8]; + public static final char WINDOW_SIDE = CP437[0xB3]; + public static final char WINDOW_LEFT_BOTTOM = CP437[0xD4]; + public static final char WINDOW_RIGHT_BOTTOM = CP437[0xBE]; + public static final char WINDOW_LEFT_TEE = CP437[0xC6]; + public static final char WINDOW_RIGHT_TEE = CP437[0xB5]; + public static final char WINDOW_SIDE_DOUBLE = CP437[0xBA]; + public static final char WINDOW_LEFT_TOP_DOUBLE = CP437[0xC9]; + public static final char WINDOW_RIGHT_TOP_DOUBLE = CP437[0xBB]; + public static final char WINDOW_LEFT_BOTTOM_DOUBLE = CP437[0xC8]; + public static final char WINDOW_RIGHT_BOTTOM_DOUBLE = CP437[0xBC]; } - diff --git a/src/jexer/bits/MnemonicString.java b/src/jexer/bits/MnemonicString.java index 0567c99..0537bbe 100644 --- a/src/jexer/bits/MnemonicString.java +++ b/src/jexer/bits/MnemonicString.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.bits; @@ -41,57 +39,56 @@ package jexer.bits; public class MnemonicString { /** - * Keyboard shortcut to activate this item + * Keyboard shortcut to activate this item. */ - public char shortcut; + private char shortcut; /** - * Location of the highlighted character + * Location of the highlighted character. */ - public int shortcutIdx = -1; + private int shortcutIdx = -1; /** - * The raw (uncolored) string + * The raw (uncolored) string. */ - public String rawLabel; + private String rawLabel; /** - * Public constructor + * Public constructor. * * @param label widget label or title. Label must contain a keyboard * shortcut, denoted by prefixing a letter with "&", e.g. "&File" */ - public MnemonicString(String label) { + public MnemonicString(final String label) { - // Setup the menu shortcut - String newLabel = ""; - boolean foundAmp = false; - boolean foundShortcut = false; - int shortcutIdx = 0; - for (int i = 0; i < label.length(); i++) { - char c = label.charAt(i); - if (c == '&') { - if (foundAmp == true) { - newLabel += '&'; - shortcutIdx++; - } else { - foundAmp = true; - } - } else { - newLabel += c; - if (foundAmp == true) { - if (foundShortcut == false) { - shortcut = c; - foundAmp = false; - foundShortcut = true; - this.shortcutIdx = shortcutIdx; - } - } else { - shortcutIdx++; - } - } - } - this.rawLabel = newLabel; + // Setup the menu shortcut + String newLabel = ""; + boolean foundAmp = false; + boolean foundShortcut = false; + int scanShortcutIdx = 0; + for (int i = 0; i < label.length(); i++) { + char c = label.charAt(i); + if (c == '&') { + if (foundAmp) { + newLabel += '&'; + scanShortcutIdx++; + } else { + foundAmp = true; + } + } else { + newLabel += c; + if (foundAmp) { + if (!foundShortcut) { + shortcut = c; + foundAmp = false; + foundShortcut = true; + shortcutIdx = scanShortcutIdx; + } + } else { + scanShortcutIdx++; + } + } + } + this.rawLabel = newLabel; } } - diff --git a/src/jexer/bits/package-info.java b/src/jexer/bits/package-info.java new file mode 100644 index 0000000..fb3a895 --- /dev/null +++ b/src/jexer/bits/package-info.java @@ -0,0 +1,36 @@ +/* + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * 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 + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ + +/** + * This package contains low-level data objects and utility functions that + * don't warrant their own separate package. + */ +package jexer.bits; diff --git a/src/jexer/event/TCommandEvent.java b/src/jexer/event/TCommandEvent.java index d27c7ea..09304d3 100644 --- a/src/jexer/event/TCommandEvent.java +++ b/src/jexer/event/TCommandEvent.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,36 +24,51 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.event; import jexer.TCommand; /** - * This class encapsulates a user command event. + * This class encapsulates a user command event. User commands can be + * generated by menu actions, keyboard accelerators, and other UI elements. + * Commands can operate on both the application and individual widgets. */ public class TCommandEvent extends TInputEvent { /** - * Command dispatched + * Command dispatched. + */ + private TCommand cmd; + + /** + * Get TCommand. + * + * @return the TCommand */ - public TCommand cmd; + public final TCommand getCmd() { + return cmd; + } /** - * Public contructor + * Public contructor. * * @param cmd the TCommand dispatched */ - public TCommandEvent(TCommand cmd) { - this.cmd = cmd; + public TCommandEvent(final TCommand cmd) { + this.cmd = cmd; } /** - * Make human-readable description of this event + * Make human-readable description of this TCommandEvent. + * + * @return displayable String */ @Override - public String toString() { - return String.format("CommandEvent: %s", cmd.toString()); + public final String toString() { + return String.format("CommandEvent: %s", cmd.toString()); } } - diff --git a/src/jexer/event/TInputEvent.java b/src/jexer/event/TInputEvent.java index aa6c478..4a3fa1b 100644 --- a/src/jexer/event/TInputEvent.java +++ b/src/jexer/event/TInputEvent.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,26 +24,38 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.event; import java.util.Date; /** - * This is the parent class of all events received from the Terminal. + * This is the parent class of all events dispatched to the UI. */ -public class TInputEvent { +public abstract class TInputEvent { /** - * Time at which event was generated + * Time at which event was generated. */ - public Date timestamp; + private Date time; + + /** + * Get time. + * + * @return the time that this event was generated + */ + public final Date getTime() { + return time; + } /** - * Public contructor + * Protected contructor. */ - public TInputEvent() { - // Save the current time - timestamp = new Date(); + protected TInputEvent() { + // Save the current time + time = new Date(); } } diff --git a/src/jexer/event/TKeypressEvent.java b/src/jexer/event/TKeypressEvent.java index 4f54df9..31bc4ae 100644 --- a/src/jexer/event/TKeypressEvent.java +++ b/src/jexer/event/TKeypressEvent.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.event; @@ -40,31 +38,33 @@ import jexer.TKeypress; public class TKeypressEvent extends TInputEvent { /** - * Keystroke received + * Keystroke received. */ public TKeypress key; /** - * Public contructor + * Public contructor sets the key to the special kbNoKey. */ public TKeypressEvent() { - key = new TKeypress(false, 0, ' ', false, false, false); + key = TKeypress.kbNoKey; } /** - * Public contructor + * Public contructor. * * @param key the TKeypress received */ - public TKeypressEvent(TKeypress key) { - this.key = key; + public TKeypressEvent(final TKeypress key) { + this.key = key; } /** - * Make human-readable description of this event + * Make human-readable description of this TKeypressEvent. + * + * @return displayable String */ @Override - public String toString() { - return String.format("Keypress: %s", key.toString()); + public final String toString() { + return String.format("Keypress: %s", key.toString()); } } diff --git a/src/jexer/event/TMenuEvent.java b/src/jexer/event/TMenuEvent.java index 38ec852..0cdca0e 100644 --- a/src/jexer/event/TMenuEvent.java +++ b/src/jexer/event/TMenuEvent.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.event; @@ -40,25 +38,35 @@ package jexer.event; public class TMenuEvent extends TInputEvent { /** - * MenuItem ID + * MenuItem ID. + */ + private short id; + + /** + * Get the MenuItem ID. + * + * @return the ID */ - public short id; + public final short getId() { + return id; + } /** - * Public contructor + * Public contructor. * * @param id the MenuItem ID */ - public TMenuEvent(short id) { - this.id = id; + public TMenuEvent(final short id) { + this.id = id; } /** - * Make human-readable description of this event + * Make human-readable description of this TMenuEvent. + * + * @return displayable String */ @Override - public String toString() { - return String.format("MenuEvent: %d", id); + public final String toString() { + return String.format("MenuEvent: %d", id); } } - diff --git a/src/jexer/event/TMouseEvent.java b/src/jexer/event/TMouseEvent.java index fd0eede..09ace1d 100644 --- a/src/jexer/event/TMouseEvent.java +++ b/src/jexer/event/TMouseEvent.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.event; @@ -37,97 +35,102 @@ package jexer.event; */ public class TMouseEvent extends TInputEvent { + /** + * The type of event generated. + */ public enum Type { - /** - * Mouse motion. X and Y will have screen coordinates. - */ - MOUSE_MOTION, - - /** - * Mouse button down. X and Y will have screen coordinates. - */ - MOUSE_DOWN, - - /** - * Mouse button up. X and Y will have screen coordinates. - */ - MOUSE_UP + /** + * Mouse motion. X and Y will have screen coordinates. + */ + MOUSE_MOTION, + + /** + * Mouse button down. X and Y will have screen coordinates. + */ + MOUSE_DOWN, + + /** + * Mouse button up. X and Y will have screen coordinates. + */ + MOUSE_UP } /** * Type of event, one of MOUSE_MOTION, MOUSE_UP, or MOUSE_DOWN, or - * KEYPRESS + * KEYPRESS. */ public Type type; /** - * Mouse X - relative coordinates + * Mouse X - relative coordinates. */ public int x; /** - * Mouse Y - relative coordinates + * Mouse Y - relative coordinates. */ public int y; /** - * Mouse X - absolute screen coordinates + * Mouse X - absolute screen coordinates. */ public int absoluteX; /** - * Mouse Y - absolute screen coordinate + * Mouse Y - absolute screen coordinate. */ public int absoluteY; /** - * Mouse button 1 (left button) + * Mouse button 1 (left button). */ public boolean mouse1; /** - * Mouse button 2 (right button) + * Mouse button 2 (right button). */ public boolean mouse2; /** - * Mouse button 3 (middle button) + * Mouse button 3 (middle button). */ public boolean mouse3; /** - * Mouse wheel UP (button 4) + * Mouse wheel UP (button 4). */ public boolean mouseWheelUp; /** - * Mouse wheel DOWN (button 5) + * Mouse wheel DOWN (button 5). */ public boolean mouseWheelDown; /** - * Public contructor + * Public contructor. * * @param type the type of event, MOUSE_MOTION, MOUSE_DOWN, or MOUSE_UP */ - public TMouseEvent(Type type) { - this.type = type; + public TMouseEvent(final Type type) { + this.type = type; } /** - * Make human-readable description of this event + * Make human-readable description of this TMouseEvent. + * + * @return displayable String */ @Override - public String toString() { - return String.format("Mouse: %s x %d y %d absoluteX %d absoluteY %d 1 %s 2 %s 3 %s DOWN %s UP %s", - type, - x, y, - absoluteX, absoluteY, - mouse1, - mouse2, - mouse3, - mouseWheelUp, - mouseWheelDown); + public final String toString() { + return String.format("Mouse: %s x %d y %d absoluteX %d absoluteY %d 1 %s 2 %s 3 %s DOWN %s UP %s", + type, + x, y, + absoluteX, absoluteY, + mouse1, + mouse2, + mouse3, + mouseWheelUp, + mouseWheelDown); } } diff --git a/src/jexer/event/TResizeEvent.java b/src/jexer/event/TResizeEvent.java index 101b8f3..e0dcb6d 100644 --- a/src/jexer/event/TResizeEvent.java +++ b/src/jexer/event/TResizeEvent.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.event; @@ -42,45 +40,81 @@ public class TResizeEvent extends TInputEvent { * widget/window resize. */ public enum Type { - Screen, - Widget + /** + * The entire screen size changed. + */ + SCREEN, + + /** + * A widget was resized. + */ + WIDGET + } + + /** + * The type of resize. + */ + private Type type; + + /** + * Get resize type. + * + * @return SCREEN or WIDGET + */ + public final Type getType() { + return type; } /** - * The type of resize + * New width. + */ + private int width; + + /** + * Get the new width. + * + * @return width */ - public Type type; + public final int getWidth() { + return width; + } /** - * New width + * New height. */ - public int width; + private int height; /** - * New height + * Get the new height. + * + * @return height */ - public int height; + public final int getHeight() { + return width; + } /** - * Public contructor + * Public contructor. * * @param type the Type of resize, Screen or Widget * @param width the new width * @param height the new height */ - public TResizeEvent(Type type, int width, int height) { - this.type = type; - this.width = width; - this.height = height; + public TResizeEvent(final Type type, final int width, final int height) { + this.type = type; + this.width = width; + this.height = height; } /** - * Make human-readable description of this event + * Make human-readable description of this TResizeEvent. + * + * @return displayable String */ @Override - public String toString() { - return String.format("Resize: %s width = %d height = %d", - type, width, height); + public final String toString() { + return String.format("Resize: %s width = %d height = %d", + type, width, height); } } diff --git a/src/jexer/event/package-info.java b/src/jexer/event/package-info.java new file mode 100644 index 0000000..21225cd --- /dev/null +++ b/src/jexer/event/package-info.java @@ -0,0 +1,36 @@ +/* + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * 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 + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ + +/** + * This package contains the events that are generated by both end-user I/O + * (keyboard/mouse) and other UI elements (menu/resize). + */ +package jexer.event; diff --git a/src/jexer/io/ECMA48Screen.java b/src/jexer/io/ECMA48Screen.java index 2e46e39..15dee50 100644 --- a/src/jexer/io/ECMA48Screen.java +++ b/src/jexer/io/ECMA48Screen.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.io; @@ -41,184 +39,195 @@ import jexer.bits.CellAttributes; public class ECMA48Screen extends Screen { /** - * We call terminal.cursor() so need the instance + * Emit debugging to stderr. + */ + private boolean debugToStderr; + + /** + * We call terminal.cursor() so need the instance. */ private ECMA48Terminal terminal; /** - * Public constructor + * Public constructor. * * @param terminal ECMA48Terminal to use */ - public ECMA48Screen(ECMA48Terminal terminal) { - this.terminal = terminal; + public ECMA48Screen(final ECMA48Terminal terminal) { + debugToStderr = false; + + this.terminal = terminal; - // Query the screen size - setDimensions(terminal.session.getWindowWidth(), - terminal.session.getWindowHeight()); + // Query the screen size + setDimensions(terminal.getSessionInfo().getWindowWidth(), + terminal.getSessionInfo().getWindowHeight()); } /** - * Perform a somewhat-optimal rendering of a line + * Perform a somewhat-optimal rendering of a line. * * @param y row coordinate. 0 is the top-most row. * @param sb StringBuilder to write escape sequences to * @param lastAttr cell attributes from the last call to flushLine */ - private void flushLine(int y, StringBuilder sb, CellAttributes lastAttr) { - - int lastX = -1; - int textEnd = 0; - for (int x = 0; x < width; x++) { - Cell lCell = logical[x][y]; - if (!lCell.isBlank()) { - textEnd = x; - } - } - // Push textEnd to first column beyond the text area - textEnd++; - - // DEBUG - // reallyCleared = true; - - for (int x = 0; x < width; x++) { - Cell lCell = logical[x][y]; - Cell pCell = physical[x][y]; - - if ((lCell != pCell) || (reallyCleared == true)) { - - if (debugToStderr) { - System.err.printf("\n--\n"); - System.err.printf(" Y: %d X: %d\n", y, x); - System.err.printf(" lCell: %s\n", lCell); - System.err.printf(" pCell: %s\n", pCell); - System.err.printf(" ==== \n"); - } - - if (lastAttr == null) { - lastAttr = new CellAttributes(); - sb.append(terminal.normal()); - } - - // Place the cell - if ((lastX != (x - 1)) || (lastX == -1)) { - // Advancing at least one cell, or the first gotoXY - sb.append(terminal.gotoXY(x, y)); - } - - assert(lastAttr != null); - - if ((x == textEnd) && (textEnd < width - 1)) { - assert(lCell.isBlank()); - - for (int i = x; i < width; i++) { - assert(logical[i][y].isBlank()); - // Physical is always updatesd - physical[i][y].reset(); - } - - // Clear remaining line - sb.append(terminal.clearRemainingLine()); - lastAttr.reset(); - return; - } - - // Now emit only the modified attributes - if ((lCell.foreColor != lastAttr.foreColor) && - (lCell.backColor != lastAttr.backColor) && - (lCell.bold == lastAttr.bold) && - (lCell.reverse == lastAttr.reverse) && - (lCell.underline == lastAttr.underline) && - (lCell.blink == lastAttr.blink)) { - - // Both colors changed, attributes the same - sb.append(terminal.color(lCell.foreColor, - lCell.backColor)); - - if (debugToStderr) { - System.err.printf("1 Change only fore/back colors\n"); - } - } else if ((lCell.foreColor != lastAttr.foreColor) && - (lCell.backColor != lastAttr.backColor) && - (lCell.bold != lastAttr.bold) && - (lCell.reverse != lastAttr.reverse) && - (lCell.underline != lastAttr.underline) && - (lCell.blink != lastAttr.blink)) { - - if (debugToStderr) { - System.err.printf("2 Set all attributes\n"); - } - - // Everything is different - sb.append(terminal.color(lCell.foreColor, - lCell.backColor, - lCell.bold, lCell.reverse, lCell.blink, - lCell.underline)); - - } else if ((lCell.foreColor != lastAttr.foreColor) && - (lCell.backColor == lastAttr.backColor) && - (lCell.bold == lastAttr.bold) && - (lCell.reverse == lastAttr.reverse) && - (lCell.underline == lastAttr.underline) && - (lCell.blink == lastAttr.blink)) { - - // Attributes same, foreColor different - sb.append(terminal.color(lCell.foreColor, true)); - - if (debugToStderr) { - System.err.printf("3 Change foreColor\n"); - } - - } else if ((lCell.foreColor == lastAttr.foreColor) && - (lCell.backColor != lastAttr.backColor) && - (lCell.bold == lastAttr.bold) && - (lCell.reverse == lastAttr.reverse) && - (lCell.underline == lastAttr.underline) && - (lCell.blink == lastAttr.blink)) { - - // Attributes same, backColor different - sb.append(terminal.color(lCell.backColor, false)); - - if (debugToStderr) { - System.err.printf("4 Change backColor\n"); - } - - } else if ((lCell.foreColor == lastAttr.foreColor) && - (lCell.backColor == lastAttr.backColor) && - (lCell.bold == lastAttr.bold) && - (lCell.reverse == lastAttr.reverse) && - (lCell.underline == lastAttr.underline) && - (lCell.blink == lastAttr.blink)) { - - // All attributes the same, just print the char - // NOP - - if (debugToStderr) { - System.err.printf("5 Only emit character\n"); - } - } else { - // Just reset everything again - sb.append(terminal.color(lCell.foreColor, lCell.backColor, - lCell.bold, lCell.reverse, lCell.blink, - lCell.underline)); - - if (debugToStderr) { - System.err.printf("6 Change all attributes\n"); - } - } - // Emit the character - sb.append(lCell.ch); - - // Save the last rendered cell - lastX = x; - lastAttr.setTo(lCell); - - // Physical is always updatesd - physical[x][y].setTo(lCell); - - } // if ((lCell != pCell) || (reallyCleared == true)) - - } // for (int x = 0; x < width; x++) + private void flushLine(final int y, final StringBuilder sb, + CellAttributes lastAttr) { + + int lastX = -1; + int textEnd = 0; + for (int x = 0; x < width; x++) { + Cell lCell = logical[x][y]; + if (!lCell.isBlank()) { + textEnd = x; + } + } + // Push textEnd to first column beyond the text area + textEnd++; + + // DEBUG + // reallyCleared = true; + + for (int x = 0; x < width; x++) { + Cell lCell = logical[x][y]; + Cell pCell = physical[x][y]; + + if ((lCell != pCell) || reallyCleared) { + + if (debugToStderr) { + System.err.printf("\n--\n"); + System.err.printf(" Y: %d X: %d\n", y, x); + System.err.printf(" lCell: %s\n", lCell); + System.err.printf(" pCell: %s\n", pCell); + System.err.printf(" ==== \n"); + } + + if (lastAttr == null) { + lastAttr = new CellAttributes(); + sb.append(terminal.normal()); + } + + // Place the cell + if ((lastX != (x - 1)) || (lastX == -1)) { + // Advancing at least one cell, or the first gotoXY + sb.append(terminal.gotoXY(x, y)); + } + + assert (lastAttr != null); + + if ((x == textEnd) && (textEnd < width - 1)) { + assert (lCell.isBlank()); + + for (int i = x; i < width; i++) { + assert (logical[i][y].isBlank()); + // Physical is always updatesd + physical[i][y].reset(); + } + + // Clear remaining line + sb.append(terminal.clearRemainingLine()); + lastAttr.reset(); + return; + } + + // Now emit only the modified attributes + if ((lCell.getForeColor() != lastAttr.getForeColor()) + && (lCell.getBackColor() != lastAttr.getBackColor()) + && (lCell.getBold() == lastAttr.getBold()) + && (lCell.getReverse() == lastAttr.getReverse()) + && (lCell.getUnderline() == lastAttr.getUnderline()) + && (lCell.getBlink() == lastAttr.getBlink()) + ) { + // Both colors changed, attributes the same + sb.append(terminal.color(lCell.getForeColor(), + lCell.getBackColor())); + + if (debugToStderr) { + System.err.printf("1 Change only fore/back colors\n"); + } + } else if ((lCell.getForeColor() != lastAttr.getForeColor()) + && (lCell.getBackColor() != lastAttr.getBackColor()) + && (lCell.getBold() != lastAttr.getBold()) + && (lCell.getReverse() != lastAttr.getReverse()) + && (lCell.getUnderline() != lastAttr.getUnderline()) + && (lCell.getBlink() != lastAttr.getBlink()) + ) { + // Everything is different + sb.append(terminal.color(lCell.getForeColor(), + lCell.getBackColor(), + lCell.getBold(), lCell.getReverse(), + lCell.getBlink(), + lCell.getUnderline())); + + if (debugToStderr) { + System.err.printf("2 Set all attributes\n"); + } + } else if ((lCell.getForeColor() != lastAttr.getForeColor()) + && (lCell.getBackColor() == lastAttr.getBackColor()) + && (lCell.getBold() == lastAttr.getBold()) + && (lCell.getReverse() == lastAttr.getReverse()) + && (lCell.getUnderline() == lastAttr.getUnderline()) + && (lCell.getBlink() == lastAttr.getBlink()) + ) { + + // Attributes same, foreColor different + sb.append(terminal.color(lCell.getForeColor(), true)); + + if (debugToStderr) { + System.err.printf("3 Change foreColor\n"); + } + } else if ((lCell.getForeColor() == lastAttr.getForeColor()) + && (lCell.getBackColor() != lastAttr.getBackColor()) + && (lCell.getBold() == lastAttr.getBold()) + && (lCell.getReverse() == lastAttr.getReverse()) + && (lCell.getUnderline() == lastAttr.getUnderline()) + && (lCell.getBlink() == lastAttr.getBlink()) + ) { + // Attributes same, backColor different + sb.append(terminal.color(lCell.getBackColor(), false)); + + if (debugToStderr) { + System.err.printf("4 Change backColor\n"); + } + } else if ((lCell.getForeColor() == lastAttr.getForeColor()) + && (lCell.getBackColor() == lastAttr.getBackColor()) + && (lCell.getBold() == lastAttr.getBold()) + && (lCell.getReverse() == lastAttr.getReverse()) + && (lCell.getUnderline() == lastAttr.getUnderline()) + && (lCell.getBlink() == lastAttr.getBlink()) + ) { + + // All attributes the same, just print the char + // NOP + + if (debugToStderr) { + System.err.printf("5 Only emit character\n"); + } + } else { + // Just reset everything again + sb.append(terminal.color(lCell.getForeColor(), + lCell.getBackColor(), + lCell.getBold(), + lCell.getReverse(), + lCell.getBlink(), + lCell.getUnderline())); + + if (debugToStderr) { + System.err.printf("6 Change all attributes\n"); + } + } + // Emit the character + sb.append(lCell.getChar()); + + // Save the last rendered cell + lastX = x; + lastAttr.setTo(lCell); + + // Physical is always updatesd + physical[x][y].setTo(lCell); + + } // if ((lCell != pCell) || (reallyCleared == true)) + + } // for (int x = 0; x < width; x++) } /** @@ -229,31 +238,31 @@ public class ECMA48Screen extends Screen { * physical screen */ public String flushString() { - if (dirty == false) { - assert(reallyCleared == false); - return ""; - } - - CellAttributes attr = null; - - StringBuilder sb = new StringBuilder(); - if (reallyCleared == true) { - attr = new CellAttributes(); - sb.append(terminal.clearAll()); - } - - for (int y = 0; y < height; y++) { - flushLine(y, sb, attr); - } - - dirty = false; - reallyCleared = false; - - String result = sb.toString(); - if (debugToStderr) { - System.err.printf("flushString(): %s\n", result); - } - return result; + if (!dirty) { + assert (!reallyCleared); + return ""; + } + + CellAttributes attr = null; + + StringBuilder sb = new StringBuilder(); + if (reallyCleared) { + attr = new CellAttributes(); + sb.append(terminal.clearAll()); + } + + for (int y = 0; y < height; y++) { + flushLine(y, sb, attr); + } + + dirty = false; + reallyCleared = false; + + String result = sb.toString(); + if (debugToStderr) { + System.err.printf("flushString(): %s\n", result); + } + return result; } /** @@ -261,17 +270,17 @@ public class ECMA48Screen extends Screen { */ @Override public void flushPhysical() { - String result = flushString(); - if ((cursorVisible) && - (cursorY <= height - 1) && - (cursorX <= width - 1) - ) { - result += terminal.cursor(true); - result += terminal.gotoXY(cursorX, cursorY); - } else { - result += terminal.cursor(false); - } - terminal.getOutput().write(result); - terminal.flush(); + String result = flushString(); + if ((cursorVisible) + && (cursorY <= height - 1) + && (cursorX <= width - 1) + ) { + result += terminal.cursor(true); + result += terminal.gotoXY(cursorX, cursorY); + } else { + result += terminal.cursor(false); + } + terminal.getOutput().write(result); + terminal.flush(); } } diff --git a/src/jexer/io/ECMA48Terminal.java b/src/jexer/io/ECMA48Terminal.java index d7d2391..6defbe4 100644 --- a/src/jexer/io/ECMA48Terminal.java +++ b/src/jexer/io/ECMA48Terminal.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.io; @@ -60,19 +58,27 @@ import jexer.session.TTYSessionInfo; import static jexer.TKeypress.*; /** - * This class has convenience methods for emitting output to ANSI - * X3.64 / ECMA-48 type terminals e.g. xterm, linux, vt100, ansi.sys, - * etc. + * This class reads keystrokes and mouse events and emits output to ANSI + * X3.64 / ECMA-48 type terminals e.g. xterm, linux, vt100, ansi.sys, etc. */ public class ECMA48Terminal implements Runnable { /** - * The session information + * The session information. + */ + private SessionInfo sessionInfo; + + /** + * Getter for sessionInfo. + * + * @return the SessionInfo */ - public SessionInfo session; + public final SessionInfo getSessionInfo() { + return sessionInfo; + } /** - * The event queue, filled up by a thread reading on input + * The event queue, filled up by a thread reading on input. */ private List eventQueue; @@ -82,7 +88,7 @@ public class ECMA48Terminal implements Runnable { private boolean stopReaderThread; /** - * The reader thread + * The reader thread. */ private Thread readerThread; @@ -98,27 +104,26 @@ public class ECMA48Terminal implements Runnable { private int paramI; /** - * States in the input parser + * States in the input parser. */ private enum ParseState { - GROUND, - ESCAPE, - ESCAPE_INTERMEDIATE, - CSI_ENTRY, - CSI_PARAM, - // CSI_INTERMEDIATE, - MOUSE + GROUND, + ESCAPE, + ESCAPE_INTERMEDIATE, + CSI_ENTRY, + CSI_PARAM, + // CSI_INTERMEDIATE, + MOUSE } /** - * Current parsing state + * Current parsing state. */ private ParseState state; /** - * The time we entered ESCAPE. If we get a bare escape - * without a code following it, this is used to return that bare - * escape. + * The time we entered ESCAPE. If we get a bare escape without a code + * following it, this is used to return that bare escape. */ private long escapeTime; @@ -190,7 +195,7 @@ public class ECMA48Terminal implements Runnable { * @return the Writer */ public PrintWriter getOutput() { - return output; + return output; } /** @@ -199,23 +204,29 @@ public class ECMA48Terminal implements Runnable { * @return if true, getEvents() has something to return to the backend */ public boolean hasEvents() { - synchronized (eventQueue) { - return (eventQueue.size() > 0); - } + synchronized (eventQueue) { + return (eventQueue.size() > 0); + } } /** - * Call 'stty cooked' to set cooked mode. + * Call 'stty' to set cooked mode. + * + *

Actually executes '/bin/sh -c stty sane cooked < /dev/tty' */ private void sttyCooked() { - doStty(false); + doStty(false); } /** - * Call 'stty raw' to set raw mode. + * Call 'stty' to set raw mode. + * + *

Actually executes '/bin/sh -c stty -ignbrk -brkint -parmrk -istrip + * -inlcr -igncr -icrnl -ixon -opost -echo -echonl -icanon -isig -iexten + * -parenb cs8 min 1 < /dev/tty' */ private void sttyRaw() { - doStty(true); + doStty(true); } /** @@ -223,49 +234,49 @@ public class ECMA48Terminal implements Runnable { * * @param mode if true, set raw mode, otherwise set cooked mode */ - private void doStty(boolean mode) { - String [] cmdRaw = { - "/bin/sh", "-c", "stty -ignbrk -brkint -parmrk -istrip -inlcr -igncr -icrnl -ixon -opost -echo -echonl -icanon -isig -iexten -parenb cs8 min 1 < /dev/tty" - }; - String [] cmdCooked = { - "/bin/sh", "-c", "stty sane cooked < /dev/tty" - }; - try { - Process process; - if (mode == true) { - process = Runtime.getRuntime().exec(cmdRaw); - } else { - process = Runtime.getRuntime().exec(cmdCooked); - } - BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); - String line = in.readLine(); - if ((line != null) && (line.length() > 0)) { - System.err.println("WEIRD?! Normal output from stty: " + line); - } - while (true) { - BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); - line = err.readLine(); - if ((line != null) && (line.length() > 0)) { - System.err.println("Error output from stty: " + line); - } - try{ - process.waitFor(); - break; - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - int rc = process.exitValue(); - if (rc != 0) { - System.err.println("stty returned error code: " + rc); - } - } catch (IOException e) { - e.printStackTrace(); - } + private void doStty(final boolean mode) { + String [] cmdRaw = { + "/bin/sh", "-c", "stty -ignbrk -brkint -parmrk -istrip -inlcr -igncr -icrnl -ixon -opost -echo -echonl -icanon -isig -iexten -parenb cs8 min 1 < /dev/tty" + }; + String [] cmdCooked = { + "/bin/sh", "-c", "stty sane cooked < /dev/tty" + }; + try { + Process process; + if (mode == true) { + process = Runtime.getRuntime().exec(cmdRaw); + } else { + process = Runtime.getRuntime().exec(cmdCooked); + } + BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); + String line = in.readLine(); + if ((line != null) && (line.length() > 0)) { + System.err.println("WEIRD?! Normal output from stty: " + line); + } + while (true) { + BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); + line = err.readLine(); + if ((line != null) && (line.length() > 0)) { + System.err.println("Error output from stty: " + line); + } + try { + process.waitFor(); + break; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + int rc = process.exitValue(); + if (rc != 0) { + System.err.println("stty returned error code: " + rc); + } + } catch (IOException e) { + e.printStackTrace(); + } } /** - * Constructor sets up state for getEvent() + * Constructor sets up state for getEvent(). * * @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 @@ -274,159 +285,162 @@ public class ECMA48Terminal implements Runnable { * @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. + * @throws UnsupportedEncodingException if an exception is thrown when + * creating the InputStreamReader */ - public ECMA48Terminal(InputStream input, OutputStream output) throws UnsupportedEncodingException { - - reset(); - mouse1 = false; - mouse2 = false; - mouse3 = false; - stopReaderThread = false; - - if (input == null) { - // inputStream = System.in; - inputStream = new FileInputStream(FileDescriptor.in); - sttyRaw(); - setRawMode = true; - } else { - inputStream = input; - } - this.input = new InputStreamReader(inputStream, "UTF-8"); - - // TODO: include TelnetSocket from NIB and have it implement - // SessionInfo - if (input instanceof SessionInfo) { - session = (SessionInfo)input; - } - if (session == null) { - if (input == null) { - // Reading right off the tty - session = new TTYSessionInfo(); - } else { - session = new TSessionInfo(); - } - } - - if (output == null) { - this.output = new PrintWriter(new OutputStreamWriter(System.out, - "UTF-8")); - } else { - this.output = new PrintWriter(new OutputStreamWriter(output, - "UTF-8")); - } - - // Enable mouse reporting and metaSendsEscape - this.output.printf("%s%s", mouse(true), xtermMetaSendsEscape(true)); - - // Hang onto the window size - windowResize = new TResizeEvent(TResizeEvent.Type.Screen, - session.getWindowWidth(), session.getWindowHeight()); - - // Spin up the input reader - eventQueue = new LinkedList(); - readerThread = new Thread(this); - readerThread.start(); + public ECMA48Terminal(final InputStream input, + final OutputStream output) throws UnsupportedEncodingException { + + reset(); + mouse1 = false; + mouse2 = false; + mouse3 = false; + stopReaderThread = false; + + if (input == null) { + // inputStream = System.in; + inputStream = new FileInputStream(FileDescriptor.in); + sttyRaw(); + setRawMode = true; + } else { + inputStream = input; + } + this.input = new InputStreamReader(inputStream, "UTF-8"); + + // TODO: include TelnetSocket from NIB and have it implement + // SessionInfo + if (input instanceof SessionInfo) { + sessionInfo = (SessionInfo) input; + } + if (sessionInfo == null) { + if (input == null) { + // Reading right off the tty + sessionInfo = new TTYSessionInfo(); + } else { + sessionInfo = new TSessionInfo(); + } + } + + if (output == null) { + this.output = new PrintWriter(new OutputStreamWriter(System.out, + "UTF-8")); + } else { + this.output = new PrintWriter(new OutputStreamWriter(output, + "UTF-8")); + } + + // Enable mouse reporting and metaSendsEscape + this.output.printf("%s%s", mouse(true), xtermMetaSendsEscape(true)); + + // Hang onto the window size + windowResize = new TResizeEvent(TResizeEvent.Type.SCREEN, + sessionInfo.getWindowWidth(), sessionInfo.getWindowHeight()); + + // Spin up the input reader + eventQueue = new LinkedList(); + readerThread = new Thread(this); + readerThread.start(); } /** - * Restore terminal to normal state + * Restore terminal to normal state. */ public void shutdown() { - // System.err.println("=== shutdown() ==="); System.err.flush(); - - // Tell the reader thread to stop looking at input - stopReaderThread = true; - try { - readerThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - // Disable mouse reporting and show cursor - output.printf("%s%s%s", mouse(false), cursor(true), normal()); - output.flush(); - - if (setRawMode) { - sttyCooked(); - setRawMode = false; - // We don't close System.in/out - } else { - // Shut down the streams, this should wake up the reader thread - // and make it exit. - try { - if (input != null) { - input.close(); - input = null; - } - if (output != null) { - output.close(); - output = null; - } - } catch (IOException e) { - e.printStackTrace(); - } - } + // System.err.println("=== shutdown() ==="); System.err.flush(); + + // Tell the reader thread to stop looking at input + stopReaderThread = true; + try { + readerThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // Disable mouse reporting and show cursor + output.printf("%s%s%s", mouse(false), cursor(true), normal()); + output.flush(); + + if (setRawMode) { + sttyCooked(); + setRawMode = false; + // We don't close System.in/out + } else { + // Shut down the streams, this should wake up the reader thread + // and make it exit. + try { + if (input != null) { + input.close(); + input = null; + } + if (output != null) { + output.close(); + output = null; + } + } catch (IOException e) { + e.printStackTrace(); + } + } } /** - * Flush output + * Flush output. */ public void flush() { - output.flush(); + output.flush(); } /** - * Reset keyboard/mouse input parser + * Reset keyboard/mouse input parser. */ private void reset() { - state = ParseState.GROUND; - params = new ArrayList(); - paramI = 0; - params.clear(); - params.add(""); + state = ParseState.GROUND; + params = new ArrayList(); + paramI = 0; + params.clear(); + params.add(""); } /** * Produce a control character or one of the special ones (ENTER, TAB, - * etc.) + * etc.). * * @param ch Unicode code point - * @return one KEYPRESS event, either a control character (e.g. isKey == + * @return one TKeypress event, either a control character (e.g. isKey == * false, ch == 'A', ctrl == true), or a special key (e.g. isKey == true, * fnKey == ESC) */ - private TKeypressEvent controlChar(char ch) { - TKeypressEvent event = new TKeypressEvent(); - - // System.err.printf("controlChar: %02x\n", ch); - - switch (ch) { - case 0x0D: - // Carriage return --> ENTER - event.key = kbEnter; - break; - case 0x0A: - // Linefeed --> ENTER - event.key = kbEnter; - break; - case 0x1B: - // ESC - event.key = kbEsc; - break; - case '\t': - // TAB - event.key = kbTab; - break; - default: - // Make all other control characters come back as the alphabetic - // character with the ctrl field set. So SOH would be 'A' + - // ctrl. - event.key = new TKeypress(false, 0, (char)(ch + 0x40), - false, true, false); - break; - } - return event; + private TKeypressEvent controlChar(final char ch) { + TKeypressEvent event = new TKeypressEvent(); + + // System.err.printf("controlChar: %02x\n", ch); + + switch (ch) { + case 0x0D: + // Carriage return --> ENTER + event.key = kbEnter; + break; + case 0x0A: + // Linefeed --> ENTER + event.key = kbEnter; + break; + case 0x1B: + // ESC + event.key = kbEsc; + break; + case '\t': + // TAB + event.key = kbTab; + break; + default: + // Make all other control characters come back as the alphabetic + // character with the ctrl field set. So SOH would be 'A' + + // ctrl. + event.key = new TKeypress(false, 0, (char)(ch + 0x40), + false, true, false); + break; + } + return event; } /** @@ -435,228 +449,228 @@ public class ECMA48Terminal implements Runnable { * @return one KEYPRESS event representing a special key */ private TInputEvent csiFnKey() { - int key = 0; - int modifier = 0; - if (params.size() > 0) { - key = Integer.parseInt(params.get(0)); - } - if (params.size() > 1) { - modifier = Integer.parseInt(params.get(1)); - } - TKeypressEvent event = new TKeypressEvent(); - - switch (modifier) { - case 0: - // No modifier - switch (key) { - case 1: - event.key = kbHome; - break; - case 2: - event.key = kbIns; - break; - case 3: - event.key = kbDel; - break; - case 4: - event.key = kbEnd; - break; - case 5: - event.key = kbPgUp; - break; - case 6: - event.key = kbPgDn; - break; - case 15: - event.key = kbF5; - break; - case 17: - event.key = kbF6; - break; - case 18: - event.key = kbF7; - break; - case 19: - event.key = kbF8; - break; - case 20: - event.key = kbF9; - break; - case 21: - event.key = kbF10; - break; - case 23: - event.key = kbF11; - break; - case 24: - event.key = kbF12; - break; - default: - // Unknown - return null; - } - - break; - case 2: - // Shift - switch (key) { - case 1: - event.key = kbShiftHome; - break; - case 2: - event.key = kbShiftIns; - break; - case 3: - event.key = kbShiftDel; - break; - case 4: - event.key = kbShiftEnd; - break; - case 5: - event.key = kbShiftPgUp; - break; - case 6: - event.key = kbShiftPgDn; - break; - case 15: - event.key = kbShiftF5; - break; - case 17: - event.key = kbShiftF6; - break; - case 18: - event.key = kbShiftF7; - break; - case 19: - event.key = kbShiftF8; - break; - case 20: - event.key = kbShiftF9; - break; - case 21: - event.key = kbShiftF10; - break; - case 23: - event.key = kbShiftF11; - break; - case 24: - event.key = kbShiftF12; - break; - default: - // Unknown - return null; - } - break; - - case 3: - // Alt - switch (key) { - case 1: - event.key = kbAltHome; - break; - case 2: - event.key = kbAltIns; - break; - case 3: - event.key = kbAltDel; - break; - case 4: - event.key = kbAltEnd; - break; - case 5: - event.key = kbAltPgUp; - break; - case 6: - event.key = kbAltPgDn; - break; - case 15: - event.key = kbAltF5; - break; - case 17: - event.key = kbAltF6; - break; - case 18: - event.key = kbAltF7; - break; - case 19: - event.key = kbAltF8; - break; - case 20: - event.key = kbAltF9; - break; - case 21: - event.key = kbAltF10; - break; - case 23: - event.key = kbAltF11; - break; - case 24: - event.key = kbAltF12; - break; - default: - // Unknown - return null; - } - break; - - case 5: - // Ctrl - switch (key) { - case 1: - event.key = kbCtrlHome; - break; - case 2: - event.key = kbCtrlIns; - break; - case 3: - event.key = kbCtrlDel; - break; - case 4: - event.key = kbCtrlEnd; - break; - case 5: - event.key = kbCtrlPgUp; - break; - case 6: - event.key = kbCtrlPgDn; - break; - case 15: - event.key = kbCtrlF5; - break; - case 17: - event.key = kbCtrlF6; - break; - case 18: - event.key = kbCtrlF7; - break; - case 19: - event.key = kbCtrlF8; - break; - case 20: - event.key = kbCtrlF9; - break; - case 21: - event.key = kbCtrlF10; - break; - case 23: - event.key = kbCtrlF11; - break; - case 24: - event.key = kbCtrlF12; - break; - default: - // Unknown - return null; - } - break; - - default: - // Unknown - return null; - } - - // All OK, return a keypress - return event; + int key = 0; + int modifier = 0; + if (params.size() > 0) { + key = Integer.parseInt(params.get(0)); + } + if (params.size() > 1) { + modifier = Integer.parseInt(params.get(1)); + } + TKeypressEvent event = new TKeypressEvent(); + + switch (modifier) { + case 0: + // No modifier + switch (key) { + case 1: + event.key = kbHome; + break; + case 2: + event.key = kbIns; + break; + case 3: + event.key = kbDel; + break; + case 4: + event.key = kbEnd; + break; + case 5: + event.key = kbPgUp; + break; + case 6: + event.key = kbPgDn; + break; + case 15: + event.key = kbF5; + break; + case 17: + event.key = kbF6; + break; + case 18: + event.key = kbF7; + break; + case 19: + event.key = kbF8; + break; + case 20: + event.key = kbF9; + break; + case 21: + event.key = kbF10; + break; + case 23: + event.key = kbF11; + break; + case 24: + event.key = kbF12; + break; + default: + // Unknown + return null; + } + + break; + case 2: + // Shift + switch (key) { + case 1: + event.key = kbShiftHome; + break; + case 2: + event.key = kbShiftIns; + break; + case 3: + event.key = kbShiftDel; + break; + case 4: + event.key = kbShiftEnd; + break; + case 5: + event.key = kbShiftPgUp; + break; + case 6: + event.key = kbShiftPgDn; + break; + case 15: + event.key = kbShiftF5; + break; + case 17: + event.key = kbShiftF6; + break; + case 18: + event.key = kbShiftF7; + break; + case 19: + event.key = kbShiftF8; + break; + case 20: + event.key = kbShiftF9; + break; + case 21: + event.key = kbShiftF10; + break; + case 23: + event.key = kbShiftF11; + break; + case 24: + event.key = kbShiftF12; + break; + default: + // Unknown + return null; + } + break; + + case 3: + // Alt + switch (key) { + case 1: + event.key = kbAltHome; + break; + case 2: + event.key = kbAltIns; + break; + case 3: + event.key = kbAltDel; + break; + case 4: + event.key = kbAltEnd; + break; + case 5: + event.key = kbAltPgUp; + break; + case 6: + event.key = kbAltPgDn; + break; + case 15: + event.key = kbAltF5; + break; + case 17: + event.key = kbAltF6; + break; + case 18: + event.key = kbAltF7; + break; + case 19: + event.key = kbAltF8; + break; + case 20: + event.key = kbAltF9; + break; + case 21: + event.key = kbAltF10; + break; + case 23: + event.key = kbAltF11; + break; + case 24: + event.key = kbAltF12; + break; + default: + // Unknown + return null; + } + break; + + case 5: + // Ctrl + switch (key) { + case 1: + event.key = kbCtrlHome; + break; + case 2: + event.key = kbCtrlIns; + break; + case 3: + event.key = kbCtrlDel; + break; + case 4: + event.key = kbCtrlEnd; + break; + case 5: + event.key = kbCtrlPgUp; + break; + case 6: + event.key = kbCtrlPgDn; + break; + case 15: + event.key = kbCtrlF5; + break; + case 17: + event.key = kbCtrlF6; + break; + case 18: + event.key = kbCtrlF7; + break; + case 19: + event.key = kbCtrlF8; + break; + case 20: + event.key = kbCtrlF9; + break; + case 21: + event.key = kbCtrlF10; + break; + case 23: + event.key = kbCtrlF11; + break; + case 24: + event.key = kbCtrlF12; + break; + default: + // Unknown + return null; + } + break; + + default: + // Unknown + return null; + } + + // All OK, return a keypress + return event; } /** @@ -667,109 +681,109 @@ public class ECMA48Terminal implements Runnable { * @return a MOUSE_MOTION, MOUSE_UP, or MOUSE_DOWN event */ private TInputEvent parseMouse() { - int buttons = params.get(0).charAt(0) - 32; - int x = params.get(0).charAt(1) - 32 - 1; - int y = params.get(0).charAt(2) - 32 - 1; - - // Clamp X and Y to the physical screen coordinates. - if (x >= windowResize.width) { - x = windowResize.width - 1; - } - if (y >= windowResize.height) { - y = windowResize.height - 1; - } - - TMouseEvent event = new TMouseEvent(TMouseEvent.Type.MOUSE_DOWN); - event.x = x; - event.y = y; - event.absoluteX = x; - event.absoluteY = y; - - // System.err.printf("buttons: %04x\r\n", buttons); - - switch (buttons) { - case 0: - event.mouse1 = true; - mouse1 = true; - break; - case 1: - event.mouse2 = true; - mouse2 = true; - break; - case 2: - event.mouse3 = true; - mouse3 = true; - break; - case 3: - // Release or Move - if (!mouse1 && !mouse2 && !mouse3) { - event.type = TMouseEvent.Type.MOUSE_MOTION; - } else { - event.type = TMouseEvent.Type.MOUSE_UP; - } - if (mouse1) { - mouse1 = false; - event.mouse1 = true; - } - if (mouse2) { - mouse2 = false; - event.mouse2 = true; - } - if (mouse3) { - mouse3 = false; - event.mouse3 = true; - } - break; - - case 32: - // Dragging with mouse1 down - event.mouse1 = true; - mouse1 = true; - event.type = TMouseEvent.Type.MOUSE_MOTION; - break; - - case 33: - // Dragging with mouse2 down - event.mouse2 = true; - mouse2 = true; - event.type = TMouseEvent.Type.MOUSE_MOTION; - break; - - case 34: - // Dragging with mouse3 down - event.mouse3 = true; - mouse3 = true; - event.type = TMouseEvent.Type.MOUSE_MOTION; - break; - - case 96: - // Dragging with mouse2 down after wheelUp - event.mouse2 = true; - mouse2 = true; - event.type = TMouseEvent.Type.MOUSE_MOTION; - break; - - case 97: - // Dragging with mouse2 down after wheelDown - event.mouse2 = true; - mouse2 = true; - event.type = TMouseEvent.Type.MOUSE_MOTION; - break; - - case 64: - event.mouseWheelUp = true; - break; - - case 65: - event.mouseWheelDown = true; - break; - - default: - // Unknown, just make it motion - event.type = TMouseEvent.Type.MOUSE_MOTION; - break; - } - return event; + int buttons = params.get(0).charAt(0) - 32; + int x = params.get(0).charAt(1) - 32 - 1; + int y = params.get(0).charAt(2) - 32 - 1; + + // Clamp X and Y to the physical screen coordinates. + if (x >= windowResize.getWidth()) { + x = windowResize.getWidth() - 1; + } + if (y >= windowResize.getHeight()) { + y = windowResize.getHeight() - 1; + } + + TMouseEvent event = new TMouseEvent(TMouseEvent.Type.MOUSE_DOWN); + event.x = x; + event.y = y; + event.absoluteX = x; + event.absoluteY = y; + + // System.err.printf("buttons: %04x\r\n", buttons); + + switch (buttons) { + case 0: + event.mouse1 = true; + mouse1 = true; + break; + case 1: + event.mouse2 = true; + mouse2 = true; + break; + case 2: + event.mouse3 = true; + mouse3 = true; + break; + case 3: + // Release or Move + if (!mouse1 && !mouse2 && !mouse3) { + event.type = TMouseEvent.Type.MOUSE_MOTION; + } else { + event.type = TMouseEvent.Type.MOUSE_UP; + } + if (mouse1) { + mouse1 = false; + event.mouse1 = true; + } + if (mouse2) { + mouse2 = false; + event.mouse2 = true; + } + if (mouse3) { + mouse3 = false; + event.mouse3 = true; + } + break; + + case 32: + // Dragging with mouse1 down + event.mouse1 = true; + mouse1 = true; + event.type = TMouseEvent.Type.MOUSE_MOTION; + break; + + case 33: + // Dragging with mouse2 down + event.mouse2 = true; + mouse2 = true; + event.type = TMouseEvent.Type.MOUSE_MOTION; + break; + + case 34: + // Dragging with mouse3 down + event.mouse3 = true; + mouse3 = true; + event.type = TMouseEvent.Type.MOUSE_MOTION; + break; + + case 96: + // Dragging with mouse2 down after wheelUp + event.mouse2 = true; + mouse2 = true; + event.type = TMouseEvent.Type.MOUSE_MOTION; + break; + + case 97: + // Dragging with mouse2 down after wheelDown + event.mouse2 = true; + mouse2 = true; + event.type = TMouseEvent.Type.MOUSE_MOTION; + break; + + case 64: + event.mouseWheelUp = true; + break; + + case 65: + event.mouseWheelDown = true; + break; + + default: + // Unknown, just make it motion + event.type = TMouseEvent.Type.MOUSE_MOTION; + break; + } + return event; } /** @@ -777,13 +791,13 @@ public class ECMA48Terminal implements Runnable { * * @param queue list to append new events to */ - public void getEvents(List queue) { - synchronized (eventQueue) { - if (eventQueue.size() > 0) { - queue.addAll(eventQueue); - eventQueue.clear(); - } - } + public void getEvents(final List queue) { + synchronized (eventQueue) { + if (eventQueue.size() > 0) { + queue.addAll(eventQueue); + eventQueue.clear(); + } + } } /** @@ -791,29 +805,30 @@ public class ECMA48Terminal implements Runnable { * * @param queue list to append new events to */ - public void getIdleEvents(List queue) { - - // Check for new window size - session.queryWindowSize(); - int newWidth = session.getWindowWidth(); - int newHeight = session.getWindowHeight(); - if ((newWidth != windowResize.width) || - (newHeight != windowResize.height)) { - TResizeEvent event = new TResizeEvent(TResizeEvent.Type.Screen, - newWidth, newHeight); - windowResize.width = newWidth; - windowResize.height = newHeight; - synchronized (eventQueue) { - eventQueue.add(event); - } - } - - synchronized (eventQueue) { - if (eventQueue.size() > 0) { - queue.addAll(eventQueue); - eventQueue.clear(); - } - } + public void getIdleEvents(final List queue) { + + // Check for new window size + sessionInfo.queryWindowSize(); + int newWidth = sessionInfo.getWindowWidth(); + int newHeight = sessionInfo.getWindowHeight(); + if ((newWidth != windowResize.getWidth()) + || (newHeight != windowResize.getHeight()) + ) { + TResizeEvent event = new TResizeEvent(TResizeEvent.Type.SCREEN, + newWidth, newHeight); + windowResize = new TResizeEvent(TResizeEvent.Type.SCREEN, + newWidth, newHeight); + synchronized (eventQueue) { + eventQueue.add(event); + } + } + + synchronized (eventQueue) { + if (eventQueue.size() > 0) { + queue.addAll(eventQueue); + eventQueue.clear(); + } + } } /** @@ -823,366 +838,366 @@ public class ECMA48Terminal implements Runnable { * @param events list to append new events to * @param ch Unicode code point */ - private void processChar(List events, char ch) { - - TKeypressEvent keypress; - Date now = new Date(); - - // ESCDELAY type timeout - if (state == ParseState.ESCAPE) { - long escDelay = now.getTime() - escapeTime; - if (escDelay > 250) { - // After 0.25 seconds, assume a true escape character - events.add(controlChar((char)0x1B)); - reset(); - } - } - - // System.err.printf("state: %s ch %c\r\n", state, ch); - - switch (state) { - case GROUND: - - if (ch == 0x1B) { - state = ParseState.ESCAPE; - escapeTime = now.getTime(); - return; - } - - if (ch <= 0x1F) { - // Control character - events.add(controlChar(ch)); - reset(); - return; - } - - if (ch >= 0x20) { - // Normal character - keypress = new TKeypressEvent(); - keypress.key.isKey = false; - keypress.key.ch = ch; - events.add(keypress); - reset(); - return; - } - - break; - - case ESCAPE: - if (ch <= 0x1F) { - // ALT-Control character - keypress = controlChar(ch); - keypress.key.alt = true; - events.add(keypress); - reset(); - return; - } - - if (ch == 'O') { - // This will be one of the function keys - state = ParseState.ESCAPE_INTERMEDIATE; - return; - } - - // '[' goes to CSI_ENTRY - if (ch == '[') { - state = ParseState.CSI_ENTRY; - return; - } - - // Everything else is assumed to be Alt-keystroke - keypress = new TKeypressEvent(); - keypress.key.isKey = false; - keypress.key.ch = ch; - keypress.key.alt = true; - if ((ch >= 'A') && (ch <= 'Z')) { - keypress.key.shift = true; - } - events.add(keypress); - reset(); - return; - - case ESCAPE_INTERMEDIATE: - if ((ch >= 'P') && (ch <= 'S')) { - // Function key - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - switch (ch) { - case 'P': - keypress.key.fnKey = TKeypress.F1; - break; - case 'Q': - keypress.key.fnKey = TKeypress.F2; - break; - case 'R': - keypress.key.fnKey = TKeypress.F3; - break; - case 'S': - keypress.key.fnKey = TKeypress.F4; - break; - default: - break; - } - events.add(keypress); - reset(); - return; - } - - // Unknown keystroke, ignore - reset(); - return; - - case CSI_ENTRY: - // Numbers - parameter values - if ((ch >= '0') && (ch <= '9')) { - params.set(paramI, params.get(paramI) + ch); - state = ParseState.CSI_PARAM; - return; - } - // Parameter separator - if (ch == ';') { - paramI++; - params.set(paramI, ""); - return; - } - - if ((ch >= 0x30) && (ch <= 0x7E)) { - switch (ch) { - case 'A': - // Up - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.UP; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'B': - // Down - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.DOWN; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'C': - // Right - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.RIGHT; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'D': - // Left - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.LEFT; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'H': - // Home - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.HOME; - events.add(keypress); - reset(); - return; - case 'F': - // End - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.END; - events.add(keypress); - reset(); - return; - case 'Z': - // CBT - Cursor backward X tab stops (default 1) - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.BTAB; - events.add(keypress); - reset(); - return; - case 'M': - // Mouse position - state = ParseState.MOUSE; - return; - default: - break; - } - } - - // Unknown keystroke, ignore - reset(); - return; - - case CSI_PARAM: - // Numbers - parameter values - if ((ch >= '0') && (ch <= '9')) { - params.set(paramI, params.get(paramI) + ch); - state = ParseState.CSI_PARAM; - return; - } - // Parameter separator - if (ch == ';') { - paramI++; - params.set(paramI, ""); - return; - } - - if (ch == '~') { - events.add(csiFnKey()); - reset(); - return; - } - - if ((ch >= 0x30) && (ch <= 0x7E)) { - switch (ch) { - case 'A': - // Up - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.UP; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'B': - // Down - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.DOWN; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'C': - // Right - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.RIGHT; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - case 'D': - // Left - keypress = new TKeypressEvent(); - keypress.key.isKey = true; - keypress.key.fnKey = TKeypress.LEFT; - if (params.size() > 1) { - if (params.get(1).equals("2")) { - keypress.key.shift = true; - } - if (params.get(1).equals("5")) { - keypress.key.ctrl = true; - } - if (params.get(1).equals("3")) { - keypress.key.alt = true; - } - } - events.add(keypress); - reset(); - return; - default: - break; - } - } - - // Unknown keystroke, ignore - reset(); - return; - - case MOUSE: - params.set(0, params.get(paramI) + ch); - if (params.get(0).length() == 3) { - // We have enough to generate a mouse event - events.add(parseMouse()); - reset(); - } - return; - - default: - break; - } - - // This "should" be impossible to reach - return; + private void processChar(final List events, final char ch) { + + TKeypressEvent keypress; + Date now = new Date(); + + // ESCDELAY type timeout + if (state == ParseState.ESCAPE) { + long escDelay = now.getTime() - escapeTime; + if (escDelay > 250) { + // After 0.25 seconds, assume a true escape character + events.add(controlChar((char)0x1B)); + reset(); + } + } + + // System.err.printf("state: %s ch %c\r\n", state, ch); + + switch (state) { + case GROUND: + + if (ch == 0x1B) { + state = ParseState.ESCAPE; + escapeTime = now.getTime(); + return; + } + + if (ch <= 0x1F) { + // Control character + events.add(controlChar(ch)); + reset(); + return; + } + + if (ch >= 0x20) { + // Normal character + keypress = new TKeypressEvent(); + keypress.key.isKey = false; + keypress.key.ch = ch; + events.add(keypress); + reset(); + return; + } + + break; + + case ESCAPE: + if (ch <= 0x1F) { + // ALT-Control character + keypress = controlChar(ch); + keypress.key.alt = true; + events.add(keypress); + reset(); + return; + } + + if (ch == 'O') { + // This will be one of the function keys + state = ParseState.ESCAPE_INTERMEDIATE; + return; + } + + // '[' goes to CSI_ENTRY + if (ch == '[') { + state = ParseState.CSI_ENTRY; + return; + } + + // Everything else is assumed to be Alt-keystroke + keypress = new TKeypressEvent(); + keypress.key.isKey = false; + keypress.key.ch = ch; + keypress.key.alt = true; + if ((ch >= 'A') && (ch <= 'Z')) { + keypress.key.shift = true; + } + events.add(keypress); + reset(); + return; + + case ESCAPE_INTERMEDIATE: + if ((ch >= 'P') && (ch <= 'S')) { + // Function key + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + switch (ch) { + case 'P': + keypress.key.fnKey = TKeypress.F1; + break; + case 'Q': + keypress.key.fnKey = TKeypress.F2; + break; + case 'R': + keypress.key.fnKey = TKeypress.F3; + break; + case 'S': + keypress.key.fnKey = TKeypress.F4; + break; + default: + break; + } + events.add(keypress); + reset(); + return; + } + + // Unknown keystroke, ignore + reset(); + return; + + case CSI_ENTRY: + // Numbers - parameter values + if ((ch >= '0') && (ch <= '9')) { + params.set(paramI, params.get(paramI) + ch); + state = ParseState.CSI_PARAM; + return; + } + // Parameter separator + if (ch == ';') { + paramI++; + params.set(paramI, ""); + return; + } + + if ((ch >= 0x30) && (ch <= 0x7E)) { + switch (ch) { + case 'A': + // Up + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.UP; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'B': + // Down + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.DOWN; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'C': + // Right + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.RIGHT; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'D': + // Left + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.LEFT; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'H': + // Home + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.HOME; + events.add(keypress); + reset(); + return; + case 'F': + // End + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.END; + events.add(keypress); + reset(); + return; + case 'Z': + // CBT - Cursor backward X tab stops (default 1) + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.BTAB; + events.add(keypress); + reset(); + return; + case 'M': + // Mouse position + state = ParseState.MOUSE; + return; + default: + break; + } + } + + // Unknown keystroke, ignore + reset(); + return; + + case CSI_PARAM: + // Numbers - parameter values + if ((ch >= '0') && (ch <= '9')) { + params.set(paramI, params.get(paramI) + ch); + state = ParseState.CSI_PARAM; + return; + } + // Parameter separator + if (ch == ';') { + paramI++; + params.set(paramI, ""); + return; + } + + if (ch == '~') { + events.add(csiFnKey()); + reset(); + return; + } + + if ((ch >= 0x30) && (ch <= 0x7E)) { + switch (ch) { + case 'A': + // Up + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.UP; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'B': + // Down + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.DOWN; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'C': + // Right + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.RIGHT; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + case 'D': + // Left + keypress = new TKeypressEvent(); + keypress.key.isKey = true; + keypress.key.fnKey = TKeypress.LEFT; + if (params.size() > 1) { + if (params.get(1).equals("2")) { + keypress.key.shift = true; + } + if (params.get(1).equals("5")) { + keypress.key.ctrl = true; + } + if (params.get(1).equals("3")) { + keypress.key.alt = true; + } + } + events.add(keypress); + reset(); + return; + default: + break; + } + } + + // Unknown keystroke, ignore + reset(); + return; + + case MOUSE: + params.set(0, params.get(paramI) + ch); + if (params.get(0).length() == 3) { + // We have enough to generate a mouse event + events.add(parseMouse()); + reset(); + } + return; + + default: + break; + } + + // This "should" be impossible to reach + return; } /** @@ -1193,11 +1208,11 @@ public class ECMA48Terminal implements Runnable { * @param on if true, enable metaSendsEscape * @return the string to emit to xterm */ - static public String xtermMetaSendsEscape(boolean on) { - if (on) { - return "\033[?1036h\033[?1034l"; - } - return "\033[?1036l"; + public String xtermMetaSendsEscape(final boolean on) { + if (on) { + return "\033[?1036h\033[?1034l"; + } + return "\033[?1036l"; } /** @@ -1209,14 +1224,14 @@ public class ECMA48Terminal implements Runnable { * @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) { - // Nix any trailing ';' because that resets all attributes - while (str.endsWith(":")) { - str = str.substring(0, str.length() - 1); - } - } - return "\033[" + str + "m"; + public String addHeaderSGR(String str) { + if (str.length() > 0) { + // Nix any trailing ';' because that resets all attributes + while (str.endsWith(":")) { + str = str.substring(0, str.length() - 1); + } + } + return "\033[" + str + "m"; } /** @@ -1227,8 +1242,8 @@ public class ECMA48Terminal implements Runnable { * @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); + public String color(final Color color, final boolean foreground) { + return color(color, foreground, true); } /** @@ -1241,23 +1256,23 @@ public class ECMA48Terminal implements Runnable { * @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) { - - int ecmaColor = color.value; - - // Convert Color.* values to SGR numerics - if (foreground == true) { - ecmaColor += 30; - } else { - ecmaColor += 40; - } - - if (header) { - return String.format("\033[%dm", ecmaColor); - } else { - return String.format("%d;", ecmaColor); - } + public String color(final Color color, final boolean foreground, + final boolean header) { + + int ecmaColor = color.getValue(); + + // Convert Color.* values to SGR numerics + if (foreground) { + ecmaColor += 30; + } else { + ecmaColor += 40; + } + + if (header) { + return String.format("\033[%dm", ecmaColor); + } else { + return String.format("%d;", ecmaColor); + } } /** @@ -1269,8 +1284,8 @@ public class ECMA48Terminal implements Runnable { * @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); + public String color(final Color foreColor, final Color backColor) { + return color(foreColor, backColor, true); } /** @@ -1284,21 +1299,21 @@ public class ECMA48Terminal implements Runnable { * @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) { + public String color(final Color foreColor, final Color backColor, + final boolean header) { - int ecmaForeColor = foreColor.value; - int ecmaBackColor = backColor.value; + int ecmaForeColor = foreColor.getValue(); + int ecmaBackColor = backColor.getValue(); - // Convert Color.* values to SGR numerics - ecmaBackColor += 40; - ecmaForeColor += 30; + // Convert Color.* values to SGR numerics + ecmaBackColor += 40; + ecmaForeColor += 30; - if (header) { - return String.format("\033[%d;%dm", ecmaForeColor, ecmaBackColor); - } else { - return String.format("%d;%d;", ecmaForeColor, ecmaBackColor); - } + if (header) { + return String.format("\033[%d;%dm", ecmaForeColor, ecmaBackColor); + } else { + return String.format("%d;%d;", ecmaForeColor, ecmaBackColor); + } } /** @@ -1315,53 +1330,54 @@ public class ECMA48Terminal implements Runnable { * @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) { - - int ecmaForeColor = foreColor.value; - int ecmaBackColor = backColor.value; - - // Convert Color.* values to SGR numerics - ecmaBackColor += 40; - ecmaForeColor += 30; - - StringBuilder sb = new StringBuilder(); - if ( bold && reverse && blink && !underline ) { - sb.append("\033[0;1;7;5;"); - } else if ( bold && reverse && !blink && !underline ) { - sb.append("\033[0;1;7;"); - } else if ( !bold && reverse && blink && !underline ) { - sb.append("\033[0;7;5;"); - } else if ( bold && !reverse && blink && !underline ) { - sb.append("\033[0;1;5;"); - } else if ( bold && !reverse && !blink && !underline ) { - sb.append("\033[0;1;"); - } else if ( !bold && reverse && !blink && !underline ) { - sb.append("\033[0;7;"); - } else if ( !bold && !reverse && blink && !underline) { - sb.append("\033[0;5;"); - } else if ( bold && reverse && blink && underline ) { - sb.append("\033[0;1;7;5;4;"); - } else if ( bold && reverse && !blink && underline ) { - sb.append("\033[0;1;7;4;"); - } else if ( !bold && reverse && blink && underline ) { - sb.append("\033[0;7;5;4;"); - } else if ( bold && !reverse && blink && underline ) { - sb.append("\033[0;1;5;4;"); - } else if ( bold && !reverse && !blink && underline ) { - sb.append("\033[0;1;4;"); - } else if ( !bold && reverse && !blink && underline ) { - sb.append("\033[0;7;4;"); - } else if ( !bold && !reverse && blink && underline) { - sb.append("\033[0;5;4;"); - } else if ( !bold && !reverse && !blink && underline) { - sb.append("\033[0;4;"); - } else { - assert(!bold && !reverse && !blink && !underline); - sb.append("\033[0;"); - } - sb.append(String.format("%d;%dm", ecmaForeColor, ecmaBackColor)); - return sb.toString(); + public String color(final Color foreColor, final Color backColor, + final boolean bold, final boolean reverse, final boolean blink, + final boolean underline) { + + int ecmaForeColor = foreColor.getValue(); + int ecmaBackColor = backColor.getValue(); + + // Convert Color.* values to SGR numerics + ecmaBackColor += 40; + ecmaForeColor += 30; + + StringBuilder sb = new StringBuilder(); + if ( bold && reverse && blink && !underline ) { + sb.append("\033[0;1;7;5;"); + } else if ( bold && reverse && !blink && !underline ) { + sb.append("\033[0;1;7;"); + } else if ( !bold && reverse && blink && !underline ) { + sb.append("\033[0;7;5;"); + } else if ( bold && !reverse && blink && !underline ) { + sb.append("\033[0;1;5;"); + } else if ( bold && !reverse && !blink && !underline ) { + sb.append("\033[0;1;"); + } else if ( !bold && reverse && !blink && !underline ) { + sb.append("\033[0;7;"); + } else if ( !bold && !reverse && blink && !underline) { + sb.append("\033[0;5;"); + } else if ( bold && reverse && blink && underline ) { + sb.append("\033[0;1;7;5;4;"); + } else if ( bold && reverse && !blink && underline ) { + sb.append("\033[0;1;7;4;"); + } else if ( !bold && reverse && blink && underline ) { + sb.append("\033[0;7;5;4;"); + } else if ( bold && !reverse && blink && underline ) { + sb.append("\033[0;1;5;4;"); + } else if ( bold && !reverse && !blink && underline ) { + sb.append("\033[0;1;4;"); + } else if ( !bold && reverse && !blink && underline ) { + sb.append("\033[0;7;4;"); + } else if ( !bold && !reverse && blink && underline) { + sb.append("\033[0;5;4;"); + } else if ( !bold && !reverse && !blink && underline) { + sb.append("\033[0;4;"); + } else { + assert (!bold && !reverse && !blink && !underline); + sb.append("\033[0;"); + } + sb.append(String.format("%d;%dm", ecmaForeColor, ecmaBackColor)); + return sb.toString(); } /** @@ -1371,11 +1387,11 @@ public class ECMA48Terminal implements Runnable { * @return the string to emit to an ANSI / ECMA-style terminal, * e.g. "\033[7m" */ - static public String reverse(boolean on) { - if (on) { - return "\033[7m"; - } - return "\033[27m"; + public String reverse(final boolean on) { + if (on) { + return "\033[7m"; + } + return "\033[27m"; } /** @@ -1384,8 +1400,8 @@ public class ECMA48Terminal implements Runnable { * @return the string to emit to an ANSI / ECMA-style terminal, * e.g. "\033[0m" */ - static public String normal() { - return normal(true); + public String normal() { + return normal(true); } /** @@ -1396,11 +1412,11 @@ public class ECMA48Terminal implements Runnable { * @return the string to emit to an ANSI / ECMA-style terminal, * e.g. "\033[0m" */ - static public String normal(boolean header) { - if (header) { - return "\033[0;37;40m"; - } - return "0;37;40"; + public String normal(final boolean header) { + if (header) { + return "\033[0;37;40m"; + } + return "0;37;40"; } /** @@ -1410,8 +1426,8 @@ public class ECMA48Terminal implements Runnable { * @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); + public String bold(final boolean on) { + return bold(on, true); } /** @@ -1423,17 +1439,17 @@ public class ECMA48Terminal implements Runnable { * @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) { - if (on) { - return "\033[1m"; - } - return "\033[22m"; - } - if (on) { - return "1;"; - } - return "22;"; + public String bold(final boolean on, final boolean header) { + if (header) { + if (on) { + return "\033[1m"; + } + return "\033[22m"; + } + if (on) { + return "1;"; + } + return "22;"; } /** @@ -1443,8 +1459,8 @@ public class ECMA48Terminal implements Runnable { * @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); + public String blink(final boolean on) { + return blink(on, true); } /** @@ -1456,17 +1472,17 @@ public class ECMA48Terminal implements Runnable { * @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) { - if (on) { - return "\033[5m"; - } - return "\033[25m"; - } - if (on) { - return "5;"; - } - return "25;"; + public String blink(final boolean on, final boolean header) { + if (header) { + if (on) { + return "\033[5m"; + } + return "\033[25m"; + } + if (on) { + return "5;"; + } + return "25;"; } /** @@ -1477,11 +1493,11 @@ public class ECMA48Terminal implements Runnable { * @return the string to emit to an ANSI / ECMA-style terminal, * e.g. "\033[4m" */ - static public String underline(boolean on) { - if (on) { - return "\033[4m"; - } - return "\033[24m"; + public String underline(final boolean on) { + if (on) { + return "\033[4m"; + } + return "\033[24m"; } /** @@ -1490,16 +1506,16 @@ public class ECMA48Terminal implements Runnable { * @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)) { - cursorOn = true; - return "\033[?25h"; - } - if (!on && (cursorOn == true)) { - cursorOn = false; - return "\033[?25l"; - } - return ""; + public String cursor(final boolean on) { + if (on && !cursorOn) { + cursorOn = true; + return "\033[?25h"; + } + if (!on && cursorOn) { + cursorOn = false; + return "\033[?25l"; + } + return ""; } /** @@ -1508,8 +1524,8 @@ public class ECMA48Terminal implements Runnable { * * @return the string to emit to an ANSI / ECMA-style terminal */ - static public String clearAll() { - return "\033[0;37;40m\033[2J"; + public String clearAll() { + return "\033[0;37;40m\033[2J"; } /** @@ -1519,8 +1535,8 @@ public class ECMA48Terminal implements Runnable { * * @return the string to emit to an ANSI / ECMA-style terminal */ - static public String clearRemainingLine() { - return "\033[0;37;40m\033[K"; + public String clearRemainingLine() { + return "\033[0;37;40m\033[K"; } /** @@ -1529,8 +1545,8 @@ public class ECMA48Terminal implements Runnable { * * @return the string to emit to an ANSI / ECMA-style terminal */ - static public String clearPreceedingLine() { - return "\033[0;37;40m\033[1K"; + public String clearPreceedingLine() { + return "\033[0;37;40m\033[1K"; } /** @@ -1539,8 +1555,8 @@ public class ECMA48Terminal implements Runnable { * * @return the string to emit to an ANSI / ECMA-style terminal */ - static public String clearLine() { - return "\033[0;37;40m\033[2K"; + public String clearLine() { + return "\033[0;37;40m\033[2K"; } /** @@ -1548,8 +1564,8 @@ public class ECMA48Terminal implements Runnable { * * @return the string to emit to an ANSI / ECMA-style terminal */ - static public String home() { - return "\033[H"; + public String home() { + return "\033[H"; } /** @@ -1559,8 +1575,8 @@ public class ECMA48Terminal implements Runnable { * @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); + public String gotoXY(final int x, final int y) { + return String.format("\033[%d;%dH", y + 1, x + 1); } /** @@ -1575,70 +1591,70 @@ public class ECMA48Terminal implements Runnable { * buffer. * @return the string to emit to xterm */ - static public String mouse(boolean on) { - if (on) { - return "\033[?1003;1005h\033[?1049h"; - } - return "\033[?1003;1005l\033[?1049l"; + public String mouse(final boolean on) { + if (on) { + return "\033[?1003;1005h\033[?1049h"; + } + return "\033[?1003;1005l\033[?1049l"; } /** * Read function runs on a separate thread. */ public void run() { - boolean done = false; - // available() will often return > 1, so we need to read in chunks to - // stay caught up. - char [] readBuffer = new char[128]; - List events = new LinkedList(); - - while ((done == false) && (stopReaderThread == false)) { - try { - // We assume that if inputStream has bytes available, then - // input won't block on read(). - int n = inputStream.available(); - if (n > 0) { - if (readBuffer.length < n) { - // The buffer wasn't big enough, make it huger - readBuffer = new char[readBuffer.length * 2]; - } - - int rc = input.read(readBuffer, 0, n); - // System.err.printf("read() %d", rc); System.err.flush(); - if (rc == -1) { - // This is EOF - done = true; - } else { - for (int i = 0; i < rc; i++) { - int ch = readBuffer[i]; - processChar(events, (char)ch); - if (events.size() > 0) { - // Add to the queue for the backend thread to - // be able to obtain. - synchronized (eventQueue) { - eventQueue.addAll(events); - } - // Now wake up the backend - synchronized (this) { - this.notifyAll(); - } - events.clear(); - } - } - } - } else { - // Wait 5 millis for more data - Thread.sleep(5); - } - // System.err.println("end while loop"); System.err.flush(); - } catch (InterruptedException e) { - // SQUASH - } catch (IOException e) { - e.printStackTrace(); - done = true; - } - } // while ((done == false) && (stopReaderThread == false)) - // System.err.println("*** run() exiting..."); System.err.flush(); + boolean done = false; + // available() will often return > 1, so we need to read in chunks to + // stay caught up. + char [] readBuffer = new char[128]; + List events = new LinkedList(); + + while (!done && !stopReaderThread) { + try { + // We assume that if inputStream has bytes available, then + // input won't block on read(). + int n = inputStream.available(); + if (n > 0) { + if (readBuffer.length < n) { + // The buffer wasn't big enough, make it huger + readBuffer = new char[readBuffer.length * 2]; + } + + int rc = input.read(readBuffer, 0, n); + // System.err.printf("read() %d", rc); System.err.flush(); + if (rc == -1) { + // This is EOF + done = true; + } else { + for (int i = 0; i < rc; i++) { + int ch = readBuffer[i]; + processChar(events, (char)ch); + if (events.size() > 0) { + // Add to the queue for the backend thread to + // be able to obtain. + synchronized (eventQueue) { + eventQueue.addAll(events); + } + // Now wake up the backend + synchronized (this) { + this.notifyAll(); + } + events.clear(); + } + } + } + } else { + // Wait 5 millis for more data + Thread.sleep(5); + } + // System.err.println("end while loop"); System.err.flush(); + } catch (InterruptedException e) { + // SQUASH + } catch (IOException e) { + e.printStackTrace(); + done = true; + } + } // while ((done == false) && (stopReaderThread == false)) + // System.err.println("*** run() exiting..."); System.err.flush(); } } diff --git a/src/jexer/io/Screen.java b/src/jexer/io/Screen.java index 1ecc304..6307254 100644 --- a/src/jexer/io/Screen.java +++ b/src/jexer/io/Screen.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.io; @@ -43,84 +41,79 @@ import jexer.bits.GraphicsChars; public abstract class Screen { /** - * Emit debugging to stderr - */ - public boolean debugToStderr; - - /** - * Width of the visible window + * Width of the visible window. */ protected int width; /** - * Height of the visible window + * Height of the visible window. */ protected int height; /** - * Drawing offset for x + * Drawing offset for x. */ public int offsetX; /** - * Drawing offset for y + * Drawing offset for y. */ public int offsetY; /** - * Ignore anything drawn right of clipRight + * Ignore anything drawn right of clipRight. */ public int clipRight; /** - * Ignore anything drawn below clipBottom + * Ignore anything drawn below clipBottom. */ public int clipBottom; /** - * Ignore anything drawn left of clipLeft + * Ignore anything drawn left of clipLeft. */ public int clipLeft; /** - * Ignore anything drawn above clipTop + * Ignore anything drawn above clipTop. */ public int clipTop; /** - * The physical screen last sent out on flush() + * The physical screen last sent out on flush(). */ protected Cell [][] physical; /** - * The logical screen being rendered to + * The logical screen being rendered to. */ protected Cell [][] logical; /** - * When true, logical != physical + * When true, logical != physical. */ public boolean dirty; /** * Set if the user explicitly wants to redraw everything starting with a - * ECMATerminal.clearAll() + * ECMATerminal.clearAll(). */ protected boolean reallyCleared; /** * If true, the cursor is visible and should be placed onscreen at - * (cursorX, cursorY) during a call to flushPhysical() + * (cursorX, cursorY) during a call to flushPhysical(). */ protected boolean cursorVisible; /** - * Cursor X position if visible + * Cursor X position if visible. */ protected int cursorX; /** - * Cursor Y position if visible + * Cursor Y position if visible. */ protected int cursorY; @@ -131,10 +124,10 @@ public abstract class Screen { * @param y row coordinate. 0 is the top-most row. * @return attributes at (x, y) */ - public CellAttributes getAttrXY(int x, int y) { - CellAttributes attr = new CellAttributes(); - attr.setTo(logical[x][y]); - return attr; + public CellAttributes getAttrXY(final int x, final int y) { + CellAttributes attr = new CellAttributes(); + attr.setTo(logical[x][y]); + return attr; } /** @@ -144,10 +137,10 @@ public abstract class Screen { * @param y row coordinate. 0 is the top-most row. * @param attr attributes to use (bold, foreColor, backColor) */ - public void putAttrXY(int x, int y, CellAttributes attr) { - putAttrXY(x, y, attr, true); + public void putAttrXY(final int x, final int y, final CellAttributes attr) { + putAttrXY(x, y, attr, true); } - + /** * Set the attributes at one location. * @@ -156,30 +149,34 @@ public abstract class Screen { * @param attr attributes to use (bold, foreColor, backColor) * @param clip if true, honor clipping/offset */ - public void putAttrXY(int x, int y, CellAttributes attr, boolean clip) { - - int X = x; - int Y = y; - - if (clip) { - if ((x < clipLeft) || (x >= clipRight) || - (y < clipTop) || (y >= clipBottom)) { - return; - } - X += offsetX; - Y += offsetY; - } - - if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) { - dirty = true; - logical[X][Y].foreColor = attr.foreColor; - logical[X][Y].backColor = attr.backColor; - logical[X][Y].bold = attr.bold; - logical[X][Y].blink = attr.blink; - logical[X][Y].reverse = attr.reverse; - logical[X][Y].underline = attr.underline; - logical[X][Y].protect = attr.protect; - } + public void putAttrXY(final int x, final int y, final CellAttributes attr, + final boolean clip) { + + int X = x; + int Y = y; + + if (clip) { + if ((x < clipLeft) + || (x >= clipRight) + || (y < clipTop) + || (y >= clipBottom) + ) { + return; + } + X += offsetX; + Y += offsetY; + } + + if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) { + dirty = true; + logical[X][Y].setForeColor(attr.getForeColor()); + logical[X][Y].setBackColor(attr.getBackColor()); + logical[X][Y].setBold(attr.getBold()); + logical[X][Y].setBlink(attr.getBlink()); + logical[X][Y].setReverse(attr.getReverse()); + logical[X][Y].setUnderline(attr.getUnderline()); + logical[X][Y].setProtect(attr.getProtect()); + } } /** @@ -188,12 +185,12 @@ public abstract class Screen { * @param ch character to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void putAll(char ch, CellAttributes attr) { - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - putCharXY(x, y, ch, attr); - } - } + public void putAll(final char ch, final CellAttributes attr) { + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + putCharXY(x, y, ch, attr); + } + } } /** @@ -203,8 +200,8 @@ public abstract class Screen { * @param y row coordinate. 0 is the top-most row. * @param ch character + attributes to draw */ - public void putCharXY(int x, int y, Cell ch) { - putCharXY(x, y, ch.ch, ch); + public void putCharXY(final int x, final int y, final Cell ch) { + putCharXY(x, y, ch.getChar(), ch); } /** @@ -215,33 +212,38 @@ public abstract class Screen { * @param ch character to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void putCharXY(int x, int y, char ch, CellAttributes attr) { - if ((x < clipLeft) || (x >= clipRight) || - (y < clipTop) || (y >= clipBottom)) { - return; - } - - int X = x + offsetX; - int Y = y + offsetY; - - // stderr.writefln("putCharXY: %d, %d, %c", X, Y, ch); - - if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) { - dirty = true; - - // Do not put control characters on the display - assert(ch >= 0x20); - assert(ch != 0x7F); - - logical[X][Y].ch = ch; - logical[X][Y].foreColor = attr.foreColor; - logical[X][Y].backColor = attr.backColor; - logical[X][Y].bold = attr.bold; - logical[X][Y].blink = attr.blink; - logical[X][Y].reverse = attr.reverse; - logical[X][Y].underline = attr.underline; - logical[X][Y].protect = attr.protect; - } + public void putCharXY(final int x, final int y, final char ch, + final CellAttributes attr) { + + if ((x < clipLeft) + || (x >= clipRight) + || (y < clipTop) + || (y >= clipBottom) + ) { + return; + } + + int X = x + offsetX; + int Y = y + offsetY; + + // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch); + + if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) { + dirty = true; + + // Do not put control characters on the display + assert (ch >= 0x20); + assert (ch != 0x7F); + + logical[X][Y].setChar(ch); + logical[X][Y].setForeColor(attr.getForeColor()); + logical[X][Y].setBackColor(attr.getBackColor()); + logical[X][Y].setBold(attr.getBold()); + logical[X][Y].setBlink(attr.getBlink()); + logical[X][Y].setReverse(attr.getReverse()); + logical[X][Y].setUnderline(attr.getUnderline()); + logical[X][Y].setProtect(attr.getProtect()); + } } /** @@ -251,21 +253,24 @@ public abstract class Screen { * @param y row coordinate. 0 is the top-most row. * @param ch character to draw */ - public void putCharXY(int x, int y, char ch) { - if ((x < clipLeft) || (x >= clipRight) || - (y < clipTop) || (y >= clipBottom)) { - return; - } + public void putCharXY(final int x, final int y, final char ch) { + if ((x < clipLeft) + || (x >= clipRight) + || (y < clipTop) + || (y >= clipBottom) + ) { + return; + } - int X = x + offsetX; - int Y = y + offsetY; + int X = x + offsetX; + int Y = y + offsetY; - // stderr.writefln("putCharXY: %d, %d, %c", X, Y, ch); + // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch); - if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) { - dirty = true; - logical[X][Y].ch = ch; - } + if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) { + dirty = true; + logical[X][Y].setChar(ch); + } } /** @@ -276,16 +281,18 @@ public abstract class Screen { * @param str string to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void putStrXY(int x, int y, String str, CellAttributes attr) { - int i = x; - for (int j = 0; j < str.length(); j++) { - char ch = str.charAt(j); - putCharXY(i, y, ch, attr); - i++; - if (i == width) { - break; - } - } + public void putStrXY(final int x, final int y, final String str, + final CellAttributes attr) { + + int i = x; + for (int j = 0; j < str.length(); j++) { + char ch = str.charAt(j); + putCharXY(i, y, ch, attr); + i++; + if (i == width) { + break; + } + } } /** @@ -296,20 +303,20 @@ public abstract class Screen { * @param y row coordinate. 0 is the top-most row. * @param str string to draw */ - public void putStrXY(int x, int y, String str) { - int i = x; - for (int j = 0; j < str.length(); j++) { - char ch = str.charAt(j); - putCharXY(i, y, ch); - i++; - if (i == width) { - break; - } - } + public void putStrXY(final int x, final int y, final String str) { + int i = x; + for (int j = 0; j < str.length(); j++) { + char ch = str.charAt(j); + putCharXY(i, y, ch); + i++; + if (i == width) { + break; + } + } } /** - * Draw a vertical line from (x, y) to (x, y + n) + * Draw a vertical line from (x, y) to (x, y + n). * * @param x column coordinate. 0 is the left-most column. * @param y row coordinate. 0 is the top-most row. @@ -317,14 +324,16 @@ public abstract class Screen { * @param ch character to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void vLineXY(int x, int y, int n, char ch, CellAttributes attr) { - for (int i = y; i < y + n; i++) { - putCharXY(x, i, ch, attr); - } + public void vLineXY(final int x, final int y, final int n, final char ch, + final CellAttributes attr) { + + for (int i = y; i < y + n; i++) { + putCharXY(x, i, ch, attr); + } } /** - * Draw a horizontal line from (x, y) to (x + n, y) + * Draw a horizontal line from (x, y) to (x + n, y). * * @param x column coordinate. 0 is the left-most column. * @param y row coordinate. 0 is the top-most row. @@ -332,10 +341,12 @@ public abstract class Screen { * @param ch character to draw * @param attr attributes to use (bold, foreColor, backColor) */ - public void hLineXY(int x, int y, int n, char ch, CellAttributes attr) { - for (int i = x; i < x + n; i++) { - putCharXY(i, y, ch, attr); - } + public void hLineXY(final int x, final int y, final int n, final char ch, + final CellAttributes attr) { + + for (int i = x; i < x + n; i++) { + putCharXY(i, y, ch, attr); + } } /** @@ -344,53 +355,53 @@ public abstract class Screen { * @param width new width * @param height new height */ - private void reallocate(int width, int height) { - if (logical != null) { - for (int row = 0; row < this.height; row++) { - for (int col = 0; col < this.width; col++) { - logical[col][row] = null; - } - } - logical = null; - } - logical = new Cell[width][height]; - if (physical != null) { - for (int row = 0; row < this.height; row++) { - for (int col = 0; col < this.width; col++) { - physical[col][row] = null; - } - } - physical = null; - } - physical = new Cell[width][height]; - - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - physical[col][row] = new Cell(); - logical[col][row] = new Cell(); - } - } - - this.width = width; - this.height = height; - - clipLeft = 0; - clipTop = 0; - clipRight = width; - clipBottom = height; - - reallyCleared = true; - dirty = true; + private void reallocate(final int width, final int height) { + if (logical != null) { + for (int row = 0; row < this.height; row++) { + for (int col = 0; col < this.width; col++) { + logical[col][row] = null; + } + } + logical = null; + } + logical = new Cell[width][height]; + if (physical != null) { + for (int row = 0; row < this.height; row++) { + for (int col = 0; col < this.width; col++) { + physical[col][row] = null; + } + } + physical = null; + } + physical = new Cell[width][height]; + + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + physical[col][row] = new Cell(); + logical[col][row] = new Cell(); + } + } + + this.width = width; + this.height = height; + + clipLeft = 0; + clipTop = 0; + clipRight = width; + clipBottom = height; + + reallyCleared = true; + dirty = true; } /** * Change the width. Everything on-screen will be destroyed and must be * redrawn. - * + * * @param width new screen width */ - public void setWidth(int width) { - reallocate(width, this.height); + public void setWidth(final int width) { + reallocate(width, this.height); } /** @@ -399,8 +410,8 @@ public abstract class Screen { * * @param height new screen height */ - public void setHeight(int height) { - reallocate(this.width, height); + public void setHeight(final int height) { + reallocate(this.width, height); } /** @@ -410,8 +421,8 @@ public abstract class Screen { * @param width new screen width * @param height new screen height */ - public void setDimensions(int width, int height) { - reallocate(width, height); + public void setDimensions(final int width, final int height) { + reallocate(width, height); } /** @@ -420,7 +431,7 @@ public abstract class Screen { * @return current screen height */ public int getHeight() { - return this.height; + return this.height; } /** @@ -429,22 +440,20 @@ public abstract class Screen { * @return current screen width */ public int getWidth() { - return this.width; + return this.width; } /** * Public constructor. Sets everything to not-bold, white-on-black. */ public Screen() { - debugToStderr = false; - - offsetX = 0; - offsetY = 0; - width = 80; - height = 24; - logical = null; - physical = null; - reallocate(width, height); + offsetX = 0; + offsetY = 0; + width = 80; + height = 24; + logical = null; + physical = null; + reallocate(width, height); } /** @@ -452,32 +461,32 @@ public abstract class Screen { * clip variables. */ public void reset() { - dirty = true; - for (int row = 0; row < height; row++) { - for (int col = 0; col < width; col++) { - logical[col][row].reset(); - } - } - resetClipping(); + dirty = true; + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + logical[col][row].reset(); + } + } + resetClipping(); } /** * Flush the offset and clip variables. */ public void resetClipping() { - offsetX = 0; - offsetY = 0; - clipLeft = 0; - clipTop = 0; - clipRight = width; - clipBottom = height; + offsetX = 0; + offsetY = 0; + clipLeft = 0; + clipTop = 0; + clipRight = width; + clipBottom = height; } /** * Force the screen to be fully cleared and redrawn on the next flush(). */ public void clear() { - reset(); + reset(); } /** @@ -487,12 +496,14 @@ public abstract class Screen { * @param top top row of the box. 0 is the top-most row. * @param right right column of box * @param bottom bottom row of the box - * @param border attributes to use for the border (bold, foreColor, backColor) + * @param border attributes to use for the border * @param background attributes to use for the background */ - public void drawBox(int left, int top, int right, int bottom, - CellAttributes border, CellAttributes background) { - drawBox(left, top, right, bottom, border, background, 1, false); + public void drawBox(final int left, final int top, + final int right, final int bottom, + final CellAttributes border, final CellAttributes background) { + + drawBox(left, top, right, bottom, border, background, 1, false); } /** @@ -502,82 +513,84 @@ public abstract class Screen { * @param top top row of the box. 0 is the top-most row. * @param right right column of box * @param bottom bottom row of the box - * @param border attributes to use for the border (bold, foreColor, backColor) + * @param border attributes to use for the border * @param background attributes to use for the background - * @param borderType = 1: single-line border - * 2: double-line borders - * 3: double-line top/bottom edges and single-line left/right edges + * @param borderType if 1, draw a single-line border; if 2, draw a + * double-line border; if 3, draw double-line top/bottom edges and + * single-line left/right edges (like Qmodem) * @param shadow if true, draw a "shadow" on the box */ - public void drawBox(int left, int top, int right, int bottom, - CellAttributes border, CellAttributes background, int borderType, - boolean shadow) { - - int boxTop = top; - int boxLeft = left; - int boxWidth = right - left; - int boxHeight = bottom - top; - - char cTopLeft; - char cTopRight; - char cBottomLeft; - char cBottomRight; - char cHSide; - char cVSide; - - switch (borderType) { - case 1: - cTopLeft = GraphicsChars.ULCORNER; - cTopRight = GraphicsChars.URCORNER; - cBottomLeft = GraphicsChars.LLCORNER; - cBottomRight = GraphicsChars.LRCORNER; - cHSide = GraphicsChars.SINGLE_BAR; - cVSide = GraphicsChars.WINDOW_SIDE; - break; - - case 2: - cTopLeft = GraphicsChars.WINDOW_LEFT_TOP_DOUBLE; - cTopRight = GraphicsChars.WINDOW_RIGHT_TOP_DOUBLE; - cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM_DOUBLE; - cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM_DOUBLE; - cHSide = GraphicsChars.DOUBLE_BAR; - cVSide = GraphicsChars.WINDOW_SIDE_DOUBLE; - break; - - case 3: - cTopLeft = GraphicsChars.WINDOW_LEFT_TOP; - cTopRight = GraphicsChars.WINDOW_RIGHT_TOP; - cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM; - cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM; - cHSide = GraphicsChars.WINDOW_TOP; - cVSide = GraphicsChars.WINDOW_SIDE; - break; - default: - throw new IllegalArgumentException("Invalid border type: " + borderType); - } - - // Place the corner characters - putCharXY(left, top, cTopLeft, border); - putCharXY(left + boxWidth - 1, top, cTopRight, border); - putCharXY(left, top + boxHeight - 1, cBottomLeft, border); - putCharXY(left + boxWidth - 1, top + boxHeight - 1, cBottomRight, - border); - - // Draw the box lines - hLineXY(left + 1, top, boxWidth - 2, cHSide, border); - vLineXY(left, top + 1, boxHeight - 2, cVSide, border); - hLineXY(left + 1, top + boxHeight - 1, boxWidth - 2, cHSide, border); - vLineXY(left + boxWidth - 1, top + 1, boxHeight - 2, cVSide, border); - - // Fill in the interior background - for (int i = 1; i < boxHeight - 1; i++) { - hLineXY(1 + left, i + top, boxWidth - 2, ' ', background); - } - - if (shadow) { - // Draw a shadow - drawBoxShadow(left, top, right, bottom); - } + public void drawBox(final int left, final int top, + final int right, final int bottom, + final CellAttributes border, final CellAttributes background, + final int borderType, final boolean shadow) { + + int boxTop = top; + int boxLeft = left; + int boxWidth = right - left; + int boxHeight = bottom - top; + + char cTopLeft; + char cTopRight; + char cBottomLeft; + char cBottomRight; + char cHSide; + char cVSide; + + switch (borderType) { + case 1: + cTopLeft = GraphicsChars.ULCORNER; + cTopRight = GraphicsChars.URCORNER; + cBottomLeft = GraphicsChars.LLCORNER; + cBottomRight = GraphicsChars.LRCORNER; + cHSide = GraphicsChars.SINGLE_BAR; + cVSide = GraphicsChars.WINDOW_SIDE; + break; + + case 2: + cTopLeft = GraphicsChars.WINDOW_LEFT_TOP_DOUBLE; + cTopRight = GraphicsChars.WINDOW_RIGHT_TOP_DOUBLE; + cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM_DOUBLE; + cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM_DOUBLE; + cHSide = GraphicsChars.DOUBLE_BAR; + cVSide = GraphicsChars.WINDOW_SIDE_DOUBLE; + break; + + case 3: + cTopLeft = GraphicsChars.WINDOW_LEFT_TOP; + cTopRight = GraphicsChars.WINDOW_RIGHT_TOP; + cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM; + cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM; + cHSide = GraphicsChars.WINDOW_TOP; + cVSide = GraphicsChars.WINDOW_SIDE; + break; + default: + throw new IllegalArgumentException("Invalid border type: " + + borderType); + } + + // Place the corner characters + putCharXY(left, top, cTopLeft, border); + putCharXY(left + boxWidth - 1, top, cTopRight, border); + putCharXY(left, top + boxHeight - 1, cBottomLeft, border); + putCharXY(left + boxWidth - 1, top + boxHeight - 1, cBottomRight, + border); + + // Draw the box lines + hLineXY(left + 1, top, boxWidth - 2, cHSide, border); + vLineXY(left, top + 1, boxHeight - 2, cVSide, border); + hLineXY(left + 1, top + boxHeight - 1, boxWidth - 2, cHSide, border); + vLineXY(left + boxWidth - 1, top + 1, boxHeight - 2, cVSide, border); + + // Fill in the interior background + for (int i = 1; i < boxHeight - 1; i++) { + hLineXY(1 + left, i + top, boxWidth - 2, ' ', background); + } + + if (shadow) { + // Draw a shadow + drawBoxShadow(left, top, right, bottom); + } } /** @@ -588,33 +601,34 @@ public abstract class Screen { * @param right right column of box * @param bottom bottom row of the box */ - public void drawBoxShadow(int left, int top, int right, int bottom) { - - int boxTop = top; - int boxLeft = left; - int boxWidth = right - left; - int boxHeight = bottom - top; - CellAttributes shadowAttr = new CellAttributes(); - - // Shadows do not honor clipping but they DO honor offset. - int oldClipRight = clipRight; - int oldClipBottom = clipBottom; - /* - clipRight = boxWidth + 2; - clipBottom = boxHeight + 1; - */ - clipRight = width; - clipBottom = height; - - for (int i = 0; i < boxHeight; i++) { - putAttrXY(boxLeft + boxWidth, boxTop + 1 + i, shadowAttr); - putAttrXY(boxLeft + boxWidth + 1, boxTop + 1 + i, shadowAttr); - } - for (int i = 0; i < boxWidth; i++) { - putAttrXY(boxLeft + 2 + i, boxTop + boxHeight, shadowAttr); - } - clipRight = oldClipRight; - clipBottom = oldClipBottom; + public void drawBoxShadow(final int left, final int top, + final int right, final int bottom) { + + int boxTop = top; + int boxLeft = left; + int boxWidth = right - left; + int boxHeight = bottom - top; + CellAttributes shadowAttr = new CellAttributes(); + + // Shadows do not honor clipping but they DO honor offset. + int oldClipRight = clipRight; + int oldClipBottom = clipBottom; + /* + clipRight = boxWidth + 2; + clipBottom = boxHeight + 1; + */ + clipRight = width; + clipBottom = height; + + for (int i = 0; i < boxHeight; i++) { + putAttrXY(boxLeft + boxWidth, boxTop + 1 + i, shadowAttr); + putAttrXY(boxLeft + boxWidth + 1, boxTop + 1 + i, shadowAttr); + } + for (int i = 0; i < boxWidth; i++) { + putAttrXY(boxLeft + 2 + i, boxTop + boxHeight, shadowAttr); + } + clipRight = oldClipRight; + clipBottom = oldClipBottom; } /** @@ -630,16 +644,16 @@ public abstract class Screen { * @param x column coordinate to put the cursor on * @param y row coordinate to put the cursor on */ - public void putCursor(boolean visible, int x, int y) { - cursorVisible = visible; - cursorX = x; - cursorY = y; + public void putCursor(final boolean visible, final int x, final int y) { + cursorVisible = visible; + cursorX = x; + cursorY = y; } /** * Hide the cursor */ public void hideCursor() { - cursorVisible = false; + cursorVisible = false; } } diff --git a/src/jexer/io/package-info.java b/src/jexer/io/package-info.java new file mode 100644 index 0000000..19883ad --- /dev/null +++ b/src/jexer/io/package-info.java @@ -0,0 +1,36 @@ +/* + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * 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 + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ + +/** + * This package contains the user-facing I/O, including screen, keyboard, and + * mouse handling.. + */ +package jexer.io; diff --git a/src/jexer/package-info.java b/src/jexer/package-info.java new file mode 100644 index 0000000..87f1074 --- /dev/null +++ b/src/jexer/package-info.java @@ -0,0 +1,73 @@ +/* + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * 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 + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ + +/** + * Jexer - Java Text User Interface library + * + *

+ * This library is currently in design, but when finished it is intended to + * implement a text-based windowing system loosely reminiscient of Borland's + * Turbo Vision + * library. + * + *

+ * The library is currently under initial development, usage patterns are + * still being worked on. Generally the goal will be to build applications + * somewhat as follows: + * + *

+ *

+ * {@code
+ * import jexer.*;
+ *
+ * public class MyApplication extends TApplication {
+ *
+ *     public MyApplication() {
+ *         super();
+ *
+ *         // Create an editor window that has support for copy/paste,
+ *         // search text, arrow keys, horizontal and vertical scrollbar, etc.
+ *         addEditor();
+ *
+ *         // Create standard menus for File and Window
+ *         addFileMenu();
+ *         addWindowMenu();
+ *     }
+ *
+ *     public static void main(String [] args) {
+ *         MyApplication app = new MyApplication();
+ *         app.run();
+ *     }
+ * }
+ * }
+ * 
+ */ +package jexer; diff --git a/src/jexer/session/SessionInfo.java b/src/jexer/session/SessionInfo.java index 340ffd3..954befe 100644 --- a/src/jexer/session/SessionInfo.java +++ b/src/jexer/session/SessionInfo.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.session; @@ -39,49 +37,49 @@ package jexer.session; public interface SessionInfo { /** - * Username getter + * Username getter. * * @return the username */ public String getUsername(); /** - * Username setter + * Username setter. * * @param username the value */ public void setUsername(String username); /** - * Language getter + * Language getter. * * @return the language */ public String getLanguage(); /** - * Language setter + * Language setter. * * @param language the value */ public void setLanguage(String language); /** - * Text window width getter + * Text window width getter. * * @return the window width */ public int getWindowWidth(); /** - * Text window height getter + * Text window height getter. * * @return the window height */ public int getWindowHeight(); /** - * Re-query the text window size + * Re-query the text window size. */ public void queryWindowSize(); } diff --git a/src/jexer/session/TSessionInfo.java b/src/jexer/session/TSessionInfo.java index 1575a6c..9fc5676 100644 --- a/src/jexer/session/TSessionInfo.java +++ b/src/jexer/session/TSessionInfo.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.session; @@ -36,87 +34,87 @@ package jexer.session; * TSessionInfo provides a default session implementation. The username is * blank, language is "en_US", with a 80x24 text window. */ -public class TSessionInfo implements SessionInfo { +public final class TSessionInfo implements SessionInfo { /** - * User name + * User name. */ private String username = ""; /** - * Language + * Language. */ private String language = "en_US"; /** - * Text window width + * Text window width. */ private int windowWidth = 80; /** - * Text window height + * Text window height. */ private int windowHeight = 24; /** - * Username getter + * Username getter. * * @return the username */ public String getUsername() { - return this.username; + return this.username; } /** - * Username setter + * Username setter. * * @param username the value */ - public void setUsername(String username) { - this.username = username; + public void setUsername(final String username) { + this.username = username; } /** - * Language getter + * Language getter. * * @return the language */ public String getLanguage() { - return this.language; + return this.language; } /** - * Language setter + * Language setter. * * @param language the value */ - public void setLanguage(String language) { - this.language = language; + public void setLanguage(final String language) { + this.language = language; } /** - * Text window width getter + * Text window width getter. * * @return the window width */ public int getWindowWidth() { - return windowWidth; + return windowWidth; } /** - * Text window height getter + * Text window height getter. * * @return the window height */ public int getWindowHeight() { - return windowHeight; + return windowHeight; } /** - * Re-query the text window size + * Re-query the text window size. */ public void queryWindowSize() { - // NOP + // NOP } } diff --git a/src/jexer/session/TTYSessionInfo.java b/src/jexer/session/TTYSessionInfo.java index 2236ac3..080e949 100644 --- a/src/jexer/session/TTYSessionInfo.java +++ b/src/jexer/session/TTYSessionInfo.java @@ -1,16 +1,11 @@ /** * Jexer - Java Text User Interface * - * Version: $Id$ - * - * Author: Kevin Lamonte, kevin.lamonte@gmail.com - * * 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. + * 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 * @@ -29,6 +24,9 @@ * http://www.gnu.org/licenses/, or write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 */ package jexer.session; @@ -44,15 +42,15 @@ import java.util.StringTokenizer; * getpwuid(geteuid()).pw_name, language is taken from LANG, and text window * size from ioctl(TIOCGWINSIZ). */ -public class TTYSessionInfo implements SessionInfo { +public final class TTYSessionInfo implements SessionInfo { /** - * User name + * User name. */ private String username = ""; /** - * Language + * Language. */ private String language = ""; @@ -67,44 +65,44 @@ public class TTYSessionInfo implements SessionInfo { private int windowHeight = 24; /** - * Time at which the window size was refreshed + * Time at which the window size was refreshed. */ private Date lastQueryWindowTime; - + /** - * Username getter + * Username getter. * * @return the username */ public String getUsername() { - return this.username; + return this.username; } /** - * Username setter + * Username setter. * * @param username the value */ - public void setUsername(String username) { - this.username = username; + public void setUsername(final String username) { + this.username = username; } /** - * Language getter + * Language getter. * * @return the language */ public String getLanguage() { - return this.language; + return this.language; } /** - * Language setter + * Language setter. * * @param language the value */ - public void setLanguage(String language) { - this.language = language; + public void setLanguage(final String language) { + this.language = language; } /** @@ -112,96 +110,99 @@ public class TTYSessionInfo implements SessionInfo { * windowHeight are set automatically. */ private void sttyWindowSize() { - String [] cmd = { - "/bin/sh", "-c", "stty size < /dev/tty" - }; - try { - Process process = Runtime.getRuntime().exec(cmd); - BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); - String line = in.readLine(); - if ((line != null) && (line.length() > 0)) { - StringTokenizer tokenizer = new StringTokenizer(line); - windowHeight = Integer.parseInt(tokenizer.nextToken()); - windowWidth = Integer.parseInt(tokenizer.nextToken()); - } - while (true) { - BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); - line = err.readLine(); - if ((line != null) && (line.length() > 0)) { - System.err.println("Error output from stty: " + line); - } - try{ - process.waitFor(); - break; - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - int rc = process.exitValue(); - if (rc != 0) { - System.err.println("stty returned error code: " + rc); - } - } catch (IOException e) { - e.printStackTrace(); - } + String [] cmd = { + "/bin/sh", "-c", "stty size < /dev/tty" + }; + try { + Process process = Runtime.getRuntime().exec(cmd); + BufferedReader in = new BufferedReader( + new InputStreamReader(process.getInputStream(), "UTF-8")); + String line = in.readLine(); + if ((line != null) && (line.length() > 0)) { + StringTokenizer tokenizer = new StringTokenizer(line); + windowHeight = Integer.parseInt(tokenizer.nextToken()); + windowWidth = Integer.parseInt(tokenizer.nextToken()); + } + while (true) { + BufferedReader err = new BufferedReader( + new InputStreamReader(process.getErrorStream(), + "UTF-8")); + line = err.readLine(); + if ((line != null) && (line.length() > 0)) { + System.err.println("Error output from stty: " + line); + } + try { + process.waitFor(); + break; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + int rc = process.exitValue(); + if (rc != 0) { + System.err.println("stty returned error code: " + rc); + } + } catch (IOException e) { + e.printStackTrace(); + } } - + /** - * Text window width getter + * Text window width getter. * * @return the window width */ public int getWindowWidth() { - if (System.getProperty("os.name").startsWith("Windows")) { - // Always use 80x25 for Windows (same as DOS) - return 80; - } - return windowWidth; + if (System.getProperty("os.name").startsWith("Windows")) { + // Always use 80x25 for Windows (same as DOS) + return 80; + } + return windowWidth; } /** - * Text window height getter + * Text window height getter. * * @return the window height */ public int getWindowHeight() { - if (System.getProperty("os.name").startsWith("Windows")) { - // Always use 80x25 for Windows (same as DOS) - return 25; - } - return windowHeight; + if (System.getProperty("os.name").startsWith("Windows")) { + // Always use 80x25 for Windows (same as DOS) + return 25; + } + return windowHeight; } /** - * Re-query the text window size + * Re-query the text window size. */ public void queryWindowSize() { - if (lastQueryWindowTime == null) { - lastQueryWindowTime = new Date(); - } else { - Date now = new Date(); - if (now.getTime() - lastQueryWindowTime.getTime() < 3000) { - // Don't re-spawn stty, it's been too soon. - return; - } - } - if (System.getProperty("os.name").startsWith("Linux") || - System.getProperty("os.name").startsWith("Mac OS X") || - System.getProperty("os.name").startsWith("SunOS") || - System.getProperty("os.name").startsWith("FreeBSD") - ) { - // Use stty to get the window size - sttyWindowSize(); - } + if (lastQueryWindowTime == null) { + lastQueryWindowTime = new Date(); + } else { + Date now = new Date(); + if (now.getTime() - lastQueryWindowTime.getTime() < 3000) { + // Don't re-spawn stty, it's been too soon. + return; + } + } + if (System.getProperty("os.name").startsWith("Linux") + || System.getProperty("os.name").startsWith("Mac OS X") + || System.getProperty("os.name").startsWith("SunOS") + || System.getProperty("os.name").startsWith("FreeBSD") + ) { + // Use stty to get the window size + sttyWindowSize(); + } } /** - * Public constructor + * Public constructor. */ public TTYSessionInfo() { - // Populate lang and user from the environment - username = System.getProperty("user.name"); - language = System.getProperty("user.language"); - queryWindowSize(); + // Populate lang and user from the environment + username = System.getProperty("user.name"); + language = System.getProperty("user.language"); + queryWindowSize(); } } diff --git a/src/jexer/session/package-info.java b/src/jexer/session/package-info.java new file mode 100644 index 0000000..b4e2f8c --- /dev/null +++ b/src/jexer/session/package-info.java @@ -0,0 +1,36 @@ +/* + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * 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 + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ + +/** + * This package contains classes to encapsulate text terminal metadata: + * width, height, username, language, etc. + */ +package jexer.session; -- 2.27.0