Copy screen text to clipboard
[fanfix.git] / src / jexer / TApplication.java
index 4fb3bd6b2357929a712da57e70fd7f4a643f3559..a38b2daba2a95fbe382de7ffc383520f14d5ad68 100644 (file)
@@ -47,6 +47,7 @@ import java.util.ResourceBundle;
 
 import jexer.bits.Cell;
 import jexer.bits.CellAttributes;
+import jexer.bits.Clipboard;
 import jexer.bits.ColorTheme;
 import jexer.bits.StringUtils;
 import jexer.event.TCommandEvent;
@@ -148,6 +149,11 @@ public class TApplication implements Runnable {
      */
     private Backend backend;
 
+    /**
+     * The clipboard for copy and paste.
+     */
+    private Clipboard clipboard = new Clipboard();
+
     /**
      * Actual mouse coordinate X.
      */
@@ -325,6 +331,36 @@ public class TApplication implements Runnable {
      */
     private long screenResizeTime = 0;
 
+    /**
+     * If true, screen selection is a rectangle.
+     */
+    private boolean screenSelectionRectangle = false;
+
+    /**
+     * If true, the mouse is dragging a screen selection.
+     */
+    private boolean inScreenSelection = false;
+
+    /**
+     * Screen selection starting X.
+     */
+    private int screenSelectionX0;
+
+    /**
+     * Screen selection starting Y.
+     */
+    private int screenSelectionY0;
+
+    /**
+     * Screen selection ending X.
+     */
+    private int screenSelectionX1;
+
+    /**
+     * Screen selection ending Y.
+     */
+    private int screenSelectionY1;
+
     /**
      * WidgetEventHandler is the main event consumer loop.  There are at most
      * two such threads in existence: the primary for normal case and a
@@ -1157,6 +1193,28 @@ public class TApplication implements Runnable {
             typingHidMouse = false;
 
             TMouseEvent mouse = (TMouseEvent) event;
+            if (mouse.isMouse1() && (mouse.isShift() || mouse.isCtrl())) {
+                // Screen selection.
+                if (inScreenSelection) {
+                    screenSelectionX1 = mouse.getX();
+                    screenSelectionY1 = mouse.getY();
+                } else {
+                    inScreenSelection = true;
+                    screenSelectionX0 = mouse.getX();
+                    screenSelectionY0 = mouse.getY();
+                    screenSelectionX1 = mouse.getX();
+                    screenSelectionY1 = mouse.getY();
+                    screenSelectionRectangle = mouse.isCtrl();
+                }
+            } else {
+                if (inScreenSelection) {
+                    getScreen().copySelection(clipboard, screenSelectionX0,
+                        screenSelectionY0, screenSelectionX1, screenSelectionY1,
+                        screenSelectionRectangle);
+                }
+                inScreenSelection = false;
+            }
+
             if ((mouseX != mouse.getX()) || (mouseY != mouse.getY())) {
                 oldMouseX = mouseX;
                 oldMouseY = mouseY;
@@ -1726,27 +1784,15 @@ public class TApplication implements Runnable {
     // ------------------------------------------------------------------------
 
     /**
-     * Invert the cell color at a position.  This is used to track the mouse.
+     * Draw the text mouse at position.
      *
      * @param x column position
      * @param y row position
      */
-    private void invertCell(final int x, final int y) {
-        invertCell(x, y, false);
-    }
-
-    /**
-     * Invert the cell color at a position.  This is used to track the mouse.
-     *
-     * @param x column position
-     * @param y row position
-     * @param onlyThisCell if true, only invert this cell
-     */
-    private void invertCell(final int x, final int y,
-        final boolean onlyThisCell) {
+    private void drawTextMouse(final int x, final int y) {
 
         if (debugThreads) {
-            System.err.printf("%d %s invertCell() %d %d\n",
+            System.err.printf("%d %s drawTextMouse() %d %d\n",
                 System.currentTimeMillis(), Thread.currentThread(), x, y);
 
             if (activeWindow != null) {
@@ -1781,44 +1827,7 @@ public class TApplication implements Runnable {
             }
         }
 
-        Cell cell = getScreen().getCharXY(x, y);
-        if (cell.isImage()) {
-            cell.invertImage();
-        }
-        if (cell.getForeColorRGB() < 0) {
-            cell.setForeColor(cell.getForeColor().invert());
-        } else {
-            cell.setForeColorRGB(cell.getForeColorRGB() ^ 0x00ffffff);
-        }
-        if (cell.getBackColorRGB() < 0) {
-            cell.setBackColor(cell.getBackColor().invert());
-        } else {
-            cell.setBackColorRGB(cell.getBackColorRGB() ^ 0x00ffffff);
-        }
-        getScreen().putCharXY(x, y, cell);
-        if ((onlyThisCell == true) || (cell.getWidth() == Cell.Width.SINGLE)) {
-            return;
-        }
-
-        // This cell is one half of a fullwidth glyph.  Invert the other
-        // half.
-        if (cell.getWidth() == Cell.Width.LEFT) {
-            if (x < getScreen().getWidth() - 1) {
-                Cell rightHalf = getScreen().getCharXY(x + 1, y);
-                if (rightHalf.getWidth() == Cell.Width.RIGHT) {
-                    invertCell(x + 1, y, true);
-                    return;
-                }
-            }
-        }
-        if (cell.getWidth() == Cell.Width.RIGHT) {
-            if (x > 0) {
-                Cell leftHalf = getScreen().getCharXY(x - 1, y);
-                if (leftHalf.getWidth() == Cell.Width.LEFT) {
-                    invertCell(x - 1, y, true);
-                }
-            }
-        }
+        getScreen().invertCell(x, y);
     }
 
     /**
@@ -1878,9 +1887,15 @@ public class TApplication implements Runnable {
                     }
                 }
 
+                if (inScreenSelection) {
+                    getScreen().setSelection(screenSelectionX0,
+                        screenSelectionY0, screenSelectionX1, screenSelectionY1,
+                        screenSelectionRectangle);
+                }
+
                 if ((textMouse == true) && (typingHidMouse == false)) {
                     // Draw mouse at the new position.
-                    invertCell(mouseX, mouseY);
+                    drawTextMouse(mouseX, mouseY);
                 }
 
                 oldDrawnMouseX = mouseX;
@@ -2015,8 +2030,14 @@ public class TApplication implements Runnable {
                 getScreen().unsetImageRow(mouseY);
             }
         }
+
+        if (inScreenSelection) {
+            getScreen().setSelection(screenSelectionX0, screenSelectionY0,
+                screenSelectionX1, screenSelectionY1, screenSelectionRectangle);
+        }
+
         if ((textMouse == true) && (typingHidMouse == false)) {
-            invertCell(mouseX, mouseY);
+            drawTextMouse(mouseX, mouseY);
         }
         oldDrawnMouseX = mouseX;
         oldDrawnMouseY = mouseY;