LICENSE CHANGED TO MIT
[nikiroo-utils.git] / src / jexer / io / Screen.java
index 1ecc3040f4add2461348fb70df33848bb5f95328..720f8a9789f5222182bab77ec5b50fd3f74f318d 100644 (file)
@@ -1,34 +1,30 @@
-/**
+/*
  * Jexer - Java Text User Interface
  *
- * Version: $Id$
- *
- * Author: Kevin Lamonte, <a href="mailto:kevin.lamonte@gmail.com">kevin.lamonte@gmail.com</a>
- *
- * License: LGPLv3 or later
+ * The MIT License (MIT)
  *
- * Copyright: This module is licensed under the GNU Lesser General
- * Public License Version 3.  Please see the file "COPYING" in this
- * directory for more information about the GNU Lesser General Public
- * License Version 3.
+ * Copyright (C) 2016 Kevin Lamonte
  *
- *     Copyright (C) 2015  Kevin Lamonte
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
- * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
- * 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
  */
 package jexer.io;
 
@@ -43,84 +39,179 @@ import jexer.bits.GraphicsChars;
 public abstract class Screen {
 
     /**
-     * Emit debugging to stderr
+     * Width of the visible window.
      */
-    public boolean debugToStderr;
+    protected int width;
 
     /**
-     * Width of the visible window
+     * Height of the visible window.
      */
-    protected int width;
+    protected int height;
 
     /**
-     * Height of the visible window
+     * Drawing offset for x.
      */
-    protected int height;
+    private int offsetX;
+
+    /**
+     * Set drawing offset for x.
+     *
+     * @param offsetX new drawing offset
+     */
+    public final void setOffsetX(final int offsetX) {
+        this.offsetX = offsetX;
+    }
+
+    /**
+     * Drawing offset for y.
+     */
+    private int offsetY;
+
+    /**
+     * Set drawing offset for y.
+     *
+     * @param offsetY new drawing offset
+     */
+    public final void setOffsetY(final int offsetY) {
+        this.offsetY = offsetY;
+    }
+
+    /**
+     * Ignore anything drawn right of clipRight.
+     */
+    private int clipRight;
+
+    /**
+     * Get right drawing clipping boundary.
+     *
+     * @return drawing boundary
+     */
+    public final int getClipRight() {
+        return clipRight;
+    }
+
+    /**
+     * Set right drawing clipping boundary.
+     *
+     * @param clipRight new boundary
+     */
+    public final void setClipRight(final int clipRight) {
+        this.clipRight = clipRight;
+    }
 
     /**
-     * Drawing offset for x
+     * Ignore anything drawn below clipBottom.
      */
-    public int offsetX;
+    private int clipBottom;
 
     /**
-     * Drawing offset for y
+     * Get bottom drawing clipping boundary.
+     *
+     * @return drawing boundary
      */
-    public int offsetY;
+    public final int getClipBottom() {
+        return clipBottom;
+    }
 
     /**
-     * Ignore anything drawn right of clipRight
+     * Set bottom drawing clipping boundary.
+     *
+     * @param clipBottom new boundary
      */
-    public int clipRight;
+    public final void setClipBottom(final int clipBottom) {
+        this.clipBottom = clipBottom;
+    }
 
     /**
-     * Ignore anything drawn below clipBottom
+     * Ignore anything drawn left of clipLeft.
      */
-    public int clipBottom;
+    private int clipLeft;
 
     /**
-     * Ignore anything drawn left of clipLeft
+     * Get left drawing clipping boundary.
+     *
+     * @return drawing boundary
      */
-    public int clipLeft;
+    public final int getClipLeft() {
+        return clipLeft;
+    }
 
     /**
-     * Ignore anything drawn above clipTop
+     * Set left drawing clipping boundary.
+     *
+     * @param clipLeft new boundary
      */
-    public int clipTop;
+    public final void setClipLeft(final int clipLeft) {
+        this.clipLeft = clipLeft;
+    }
 
     /**
-     * The physical screen last sent out on flush()
+     * Ignore anything drawn above clipTop.
+     */
+    private int clipTop;
+
+    /**
+     * Get top drawing clipping boundary.
+     *
+     * @return drawing boundary
+     */
+    public final int getClipTop() {
+        return clipTop;
+    }
+
+    /**
+     * Set top drawing clipping boundary.
+     *
+     * @param clipTop new boundary
+     */
+    public final void setClipTop(final int clipTop) {
+        this.clipTop = clipTop;
+    }
+
+    /**
+     * 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.
+     */
+    protected volatile boolean dirty;
+
+    /**
+     * Get dirty flag.
+     *
+     * @return if true, the logical screen is not in sync with the physical
+     * screen
      */
-    public boolean dirty;
+    public final boolean isDirty() {
+        return 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 +222,12 @@ 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 final CellAttributes getAttrXY(final int x, final int y) {
+        CellAttributes attr = new CellAttributes();
+        if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+            attr.setTo(logical[x][y]);
+        }
+        return attr;
     }
 
     /**
@@ -144,10 +237,12 @@ 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 final void putAttrXY(final int x, final int y,
+        final CellAttributes attr) {
+
+        putAttrXY(x, y, attr, true);
     }
-    
+
     /**
      * Set the attributes at one location.
      *
@@ -156,30 +251,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 final 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.isBold());
+            logical[X][Y].setBlink(attr.isBlink());
+            logical[X][Y].setReverse(attr.isReverse());
+            logical[X][Y].setUnderline(attr.isUnderline());
+            logical[X][Y].setProtect(attr.isProtect());
+        }
     }
 
     /**
@@ -188,12 +287,13 @@ 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 final 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 +303,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 final void putCharXY(final int x, final int y, final Cell ch) {
+        putCharXY(x, y, ch.getChar(), ch);
     }
 
     /**
@@ -215,33 +315,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 final 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.isBold());
+            logical[X][Y].setBlink(attr.isBlink());
+            logical[X][Y].setReverse(attr.isReverse());
+            logical[X][Y].setUnderline(attr.isUnderline());
+            logical[X][Y].setProtect(attr.isProtect());
+        }
     }
 
     /**
@@ -251,21 +356,25 @@ 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 final 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 +385,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 final void putStringXY(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 +407,21 @@ 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 final void putStringXY(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 +429,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 final 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 +446,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 final 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 +460,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 synchronized 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 final synchronized void setWidth(final int width) {
+        reallocate(width, this.height);
     }
 
     /**
@@ -399,8 +515,8 @@ public abstract class Screen {
      *
      * @param height new screen height
      */
-    public void setHeight(int height) {
-       reallocate(this.width, height);
+    public final synchronized void setHeight(final int height) {
+        reallocate(this.width, height);
     }
 
     /**
@@ -410,8 +526,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 final void setDimensions(final int width, final int height) {
+        reallocate(width, height);
     }
 
     /**
@@ -419,8 +535,8 @@ public abstract class Screen {
      *
      * @return current screen height
      */
-    public int getHeight() {
-       return this.height;
+    public final synchronized int getHeight() {
+        return this.height;
     }
 
     /**
@@ -428,56 +544,66 @@ public abstract class Screen {
      *
      * @return current screen width
      */
-    public int getWidth() {
-       return this.width;
+    public final synchronized int getWidth() {
+        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);
+    protected Screen() {
+        offsetX  = 0;
+        offsetY  = 0;
+        width    = 80;
+        height   = 24;
+        logical  = null;
+        physical = null;
+        reallocate(width, height);
     }
 
     /**
      * Reset screen to not-bold, white-on-black.  Also flushes the offset and
      * 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();
+    public final synchronized void reset() {
+        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;
+    public final void resetClipping() {
+        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().
+     * Clear the logical screen.
      */
-    public void clear() {
-       reset();
+    public final void clear() {
+        reset();
+    }
+
+    /**
+     * Clear the physical screen.
+     */
+    public final void clearPhysical() {
+        dirty = true;
+        for (int row = 0; row < height; row++) {
+            for (int col = 0; col < width; col++) {
+                physical[col][row].reset();
+            }
+        }
     }
 
     /**
@@ -487,12 +613,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 final 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,126 +630,127 @@ 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);
-       }
-    }
-
-    /**
-     * Draw a box shadow
+    public final 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 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);
+        }
+    }
+
+    /**
+     * Draw a box shadow.
      *
      * @param left left column of box.  0 is the left-most row.
      * @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
      */
-    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 final 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;
     }
 
     /**
      * Subclasses must provide an implementation to push the logical screen
      * to the physical device.
      */
-    abstract public void flushPhysical();
+    public abstract void flushPhysical();
 
     /**
      * Put the cursor at (x,y).
@@ -630,16 +759,17 @@ 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
+     * Hide the cursor.
      */
-    public void hideCursor() {
-       cursorVisible = false;
+    public final void hideCursor() {
+        cursorVisible = false;
     }
 }