*/
public class LogicalScreen implements Screen {
+ // ------------------------------------------------------------------------
+ // Variables --------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
/**
* Width of the visible window.
*/
*/
private int offsetX;
+ /**
+ * Drawing offset for y.
+ */
+ private int offsetY;
+
+ /**
+ * Ignore anything drawn right of clipRight.
+ */
+ private int clipRight;
+
+ /**
+ * Ignore anything drawn below clipBottom.
+ */
+ private int clipBottom;
+
+ /**
+ * Ignore anything drawn left of clipLeft.
+ */
+ private int clipLeft;
+
+ /**
+ * Ignore anything drawn above clipTop.
+ */
+ private int clipTop;
+
+ /**
+ * The physical screen last sent out on flush().
+ */
+ protected Cell [][] physical;
+
+ /**
+ * The logical screen being rendered to.
+ */
+ protected Cell [][] logical;
+
+ /**
+ * Set if the user explicitly wants to redraw everything starting with a
+ * ECMATerminal.clearAll().
+ */
+ protected boolean reallyCleared;
+
+ /**
+ * If true, the cursor is visible and should be placed onscreen at
+ * (cursorX, cursorY) during a call to flushPhysical().
+ */
+ protected boolean cursorVisible;
+
+ /**
+ * Cursor X position if visible.
+ */
+ protected int cursorX;
+
+ /**
+ * Cursor Y position if visible.
+ */
+ protected int cursorY;
+
+ // ------------------------------------------------------------------------
+ // Constructors -----------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Public constructor. Sets everything to not-bold, white-on-black.
+ */
+ protected LogicalScreen() {
+ offsetX = 0;
+ offsetY = 0;
+ width = 80;
+ height = 24;
+ logical = null;
+ physical = null;
+ reallocate(width, height);
+ }
+
+ // ------------------------------------------------------------------------
+ // Screen -----------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
/**
* Set drawing offset for x.
*
this.offsetX = offsetX;
}
- /**
- * Drawing offset for y.
- */
- private int offsetY;
-
/**
* Set drawing offset for y.
*
this.offsetY = offsetY;
}
- /**
- * Ignore anything drawn right of clipRight.
- */
- private int clipRight;
-
/**
* Get right drawing clipping boundary.
*
this.clipRight = clipRight;
}
- /**
- * Ignore anything drawn below clipBottom.
- */
- private int clipBottom;
-
/**
* Get bottom drawing clipping boundary.
*
this.clipBottom = clipBottom;
}
- /**
- * Ignore anything drawn left of clipLeft.
- */
- private int clipLeft;
-
/**
* Get left drawing clipping boundary.
*
this.clipLeft = clipLeft;
}
- /**
- * Ignore anything drawn above clipTop.
- */
- private int clipTop;
-
/**
* Get top drawing clipping boundary.
*
this.clipTop = clipTop;
}
- /**
- * The physical screen last sent out on flush().
- */
- protected Cell [][] physical;
-
- /**
- * The logical screen being rendered to.
- */
- protected Cell [][] logical;
-
- /**
- * When true, logical != physical.
- */
- protected volatile boolean dirty;
-
/**
* Get dirty flag.
*
* screen
*/
public final boolean isDirty() {
- return dirty;
- }
-
- /**
- * Set if the user explicitly wants to redraw everything starting with a
- * ECMATerminal.clearAll().
- */
- protected boolean reallyCleared;
-
- /**
- * If true, the cursor is visible and should be placed onscreen at
- * (cursorX, cursorY) during a call to flushPhysical().
- */
- protected boolean cursorVisible;
-
- /**
- * Cursor X position if visible.
- */
- protected int cursorX;
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ if (!logical[x][y].equals(physical[x][y])) {
+ return true;
+ }
+ if (logical[x][y].isBlink()) {
+ // Blinking screens are always dirty. There is
+ // opportunity for a Netscape blink tag joke here...
+ return true;
+ }
+ }
+ }
- /**
- * Cursor Y position if visible.
- */
- protected int cursorY;
+ return false;
+ }
/**
* Get the attributes at one location.
}
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());
+ logical[X][Y].setTo(attr);
+
+ // If this happens to be the cursor position, make the position
+ // dirty.
+ if ((cursorX == X) && (cursorY == Y)) {
+ if (physical[cursorX][cursorY].getChar() == 'Q') {
+ physical[cursorX][cursorY].setChar('X');
+ } else {
+ physical[cursorX][cursorY].setChar('Q');
+ }
+ }
}
}
// 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].setTo(attr);
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());
+
+ // If this happens to be the cursor position, make the position
+ // dirty.
+ if ((cursorX == X) && (cursorY == Y)) {
+ if (physical[cursorX][cursorY].getChar() == 'Q') {
+ physical[cursorX][cursorY].setChar('X');
+ } else {
+ physical[cursorX][cursorY].setChar('Q');
+ }
+ }
}
}
// 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].setChar(ch);
+
+ // If this happens to be the cursor position, make the position
+ // dirty.
+ if ((cursorX == X) && (cursorY == Y)) {
+ if (physical[cursorX][cursorY].getChar() == 'Q') {
+ physical[cursorX][cursorY].setChar('X');
+ } else {
+ physical[cursorX][cursorY].setChar('Q');
+ }
+ }
}
}
}
}
- /**
- * Reallocate screen buffers.
- *
- * @param width new width
- * @param height new height
- */
- 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.
return this.width;
}
- /**
- * Public constructor. Sets everything to not-bold, white-on-black.
- */
- protected LogicalScreen() {
- 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 final synchronized void reset() {
- dirty = true;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
logical[col][row].reset();
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();
- }
- }
- }
-
/**
* Draw a box with a border and empty background.
*
* @param y row coordinate to put the cursor on
*/
public void putCursor(final boolean visible, final int x, final int y) {
+ if ((cursorY >= 0)
+ && (cursorX >= 0)
+ && (cursorY <= height - 1)
+ && (cursorX <= width - 1)
+ ) {
+ // Make the current cursor position dirty
+ if (physical[cursorX][cursorY].getChar() == 'Q') {
+ physical[cursorX][cursorY].setChar('X');
+ } else {
+ physical[cursorX][cursorY].setChar('Q');
+ }
+ }
cursorVisible = visible;
cursorX = x;
*/
public void setTitle(final String title) {}
+ // ------------------------------------------------------------------------
+ // LogicalScreen ----------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Reallocate screen buffers.
+ *
+ * @param width new width
+ * @param height new height
+ */
+ 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;
+ }
+
+ /**
+ * Clear the physical screen.
+ */
+ public final void clearPhysical() {
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ physical[col][row].reset();
+ }
+ }
+ }
+
}