#18 move to event-driven main loop
[fanfix.git] / src / jexer / backend / LogicalScreen.java
index 8432e4eae526f8a74f395303ebb8fbd3d5f3c09e..4e7971eaf71fce92b4fa61e32e6d3288ef05aaa4 100644 (file)
@@ -177,11 +177,6 @@ public class LogicalScreen implements Screen {
      */
     protected Cell [][] logical;
 
-    /**
-     * When true, logical != physical.
-     */
-    protected volatile boolean dirty;
-
     /**
      * Get dirty flag.
      *
@@ -189,7 +184,20 @@ public class LogicalScreen implements Screen {
      * screen
      */
     public final boolean isDirty() {
-        return dirty;
+        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;
+                }
+            }
+        }
+
+        return false;
     }
 
     /**
@@ -229,6 +237,21 @@ public class LogicalScreen implements Screen {
         return attr;
     }
 
+    /**
+     * Get the cell at one location.
+     *
+     * @param x column coordinate.  0 is the left-most column.
+     * @param y row coordinate.  0 is the top-most row.
+     * @return the character + attributes
+     */
+    public Cell getCharXY(final int x, final int y) {
+        Cell cell = new Cell();
+        if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+            cell.setTo(logical[x][y]);
+        }
+        return cell;
+    }
+
     /**
      * Set the attributes at one location.
      *
@@ -269,14 +292,7 @@ public class LogicalScreen implements Screen {
         }
 
         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);
         }
     }
 
@@ -331,20 +347,13 @@ public class LogicalScreen implements Screen {
         // 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());
         }
     }
 
@@ -371,7 +380,6 @@ public class LogicalScreen implements Screen {
         // 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);
         }
     }
@@ -495,7 +503,6 @@ public class LogicalScreen implements Screen {
         clipBottom = height;
 
         reallyCleared = true;
-        dirty = true;
     }
 
     /**
@@ -565,7 +572,6 @@ public class LogicalScreen implements Screen {
      * 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();
@@ -597,7 +603,6 @@ public class LogicalScreen implements Screen {
      * 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();
@@ -758,6 +763,18 @@ public class LogicalScreen implements Screen {
      * @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;
@@ -771,6 +788,33 @@ public class LogicalScreen implements Screen {
         cursorVisible = false;
     }
 
+    /**
+     * Get the cursor visibility.
+     *
+     * @return true if the cursor is visible
+     */
+    public boolean isCursorVisible() {
+        return cursorVisible;
+    }
+
+    /**
+     * Get the cursor X position.
+     *
+     * @return the cursor x column position
+     */
+    public int getCursorX() {
+        return cursorX;
+    }
+
+    /**
+     * Get the cursor Y position.
+     *
+     * @return the cursor y row position
+     */
+    public int getCursorY() {
+        return cursorY;
+    }
+
     /**
      * Set the window title.  Default implementation does nothing.
      *