aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Tedin2018-10-17 08:34:51 +0200
committerMartin Rudalics2018-10-17 08:34:51 +0200
commit134ba45bf0c11048c44a46c11d5dc8da12ca4d3e (patch)
treef53bdbe0caa4343fd7fbecdb6f2c09db39984079
parente64065bbbd21b7136a7a4efb4b0f2f39a65905dd (diff)
downloademacs-134ba45bf0c11048c44a46c11d5dc8da12ca4d3e.tar.gz
emacs-134ba45bf0c11048c44a46c11d5dc8da12ca4d3e.zip
Allow two mouse functions to work with Rectangle Mark mode
* lisp/mouse.el (mouse-save-then-kill): Make mouse-save-then-kill work with rectangular regions, including when mouse-drag-copy-region is set to t. (Bug#31240) (mouse-drag-and-drop-region): Allow dragging and dropping rectangular regions. (Bug#31240) * rect.el (rectangle-intersect-p) (rectangle-position-as-coordinates): New functions.
-rw-r--r--lisp/mouse.el106
-rw-r--r--lisp/rect.el31
2 files changed, 111 insertions, 26 deletions
diff --git a/lisp/mouse.el b/lisp/mouse.el
index cb63ca51c54..44cca4c868a 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -29,6 +29,8 @@
29 29
30;;; Code: 30;;; Code:
31 31
32(eval-when-compile (require 'rect))
33
32;;; Utility functions. 34;;; Utility functions.
33 35
34;; Indent track-mouse like progn. 36;; Indent track-mouse like progn.
@@ -1606,8 +1608,8 @@ if `mouse-drag-copy-region' is non-nil)"
1606 (if mouse-drag-copy-region 1608 (if mouse-drag-copy-region
1607 ;; Region already saved in the previous click; 1609 ;; Region already saved in the previous click;
1608 ;; don't make a duplicate entry, just delete. 1610 ;; don't make a duplicate entry, just delete.
1609 (delete-region (mark t) (point)) 1611 (funcall region-extract-function 'delete-only)
1610 (kill-region (mark t) (point))) 1612 (kill-region (mark t) (point) 'region))
1611 (setq mouse-selection-click-count 0) 1613 (setq mouse-selection-click-count 0)
1612 (setq mouse-save-then-kill-posn nil)) 1614 (setq mouse-save-then-kill-posn nil))
1613 1615
@@ -1632,7 +1634,7 @@ if `mouse-drag-copy-region' is non-nil)"
1632 (mouse-set-region-1) 1634 (mouse-set-region-1)
1633 (when mouse-drag-copy-region 1635 (when mouse-drag-copy-region
1634 ;; Region already copied to kill-ring once, so replace. 1636 ;; Region already copied to kill-ring once, so replace.
1635 (kill-new (filter-buffer-substring (mark t) (point)) t)) 1637 (kill-new (funcall region-extract-function nil) t))
1636 ;; Arrange for a repeated mouse-3 to kill the region. 1638 ;; Arrange for a repeated mouse-3 to kill the region.
1637 (setq mouse-save-then-kill-posn click-pt))) 1639 (setq mouse-save-then-kill-posn click-pt)))
1638 1640
@@ -2411,7 +2413,16 @@ is copied instead of being cut."
2411 (buffer (current-buffer)) 2413 (buffer (current-buffer))
2412 (window (selected-window)) 2414 (window (selected-window))
2413 (text-from-read-only buffer-read-only) 2415 (text-from-read-only buffer-read-only)
2414 (mouse-drag-and-drop-overlay (make-overlay start end)) 2416 ;; Use multiple overlays to cover cases where the region is
2417 ;; rectangular.
2418 (mouse-drag-and-drop-overlays (mapcar (lambda (bounds)
2419 (make-overlay (car bounds)
2420 (cdr bounds)))
2421 (region-bounds)))
2422 (region-noncontiguous (region-noncontiguous-p))
2423 (region-width (- (overlay-end (car mouse-drag-and-drop-overlays))
2424 (overlay-start (car mouse-drag-and-drop-overlays))))
2425 (region-height (length mouse-drag-and-drop-overlays))
2415 point-to-paste 2426 point-to-paste
2416 point-to-paste-read-only 2427 point-to-paste-read-only
2417 window-to-paste 2428 window-to-paste
@@ -2455,7 +2466,11 @@ is copied instead of being cut."
2455 ;; Obtain the dragged text in region. When the loop was 2466 ;; Obtain the dragged text in region. When the loop was
2456 ;; skipped, value-selection remains nil. 2467 ;; skipped, value-selection remains nil.
2457 (unless value-selection 2468 (unless value-selection
2458 (setq value-selection (buffer-substring start end)) 2469 (setq value-selection (funcall region-extract-function nil))
2470 ;; Remove yank-handler property in order to re-insert text using
2471 ;; the `insert-rectangle' function later on.
2472 (remove-text-properties 0 (length value-selection)
2473 '(yank-handler) value-selection)
2459 (when mouse-drag-and-drop-region-show-tooltip 2474 (when mouse-drag-and-drop-region-show-tooltip
2460 (let ((text-size mouse-drag-and-drop-region-show-tooltip)) 2475 (let ((text-size mouse-drag-and-drop-region-show-tooltip))
2461 (setq text-tooltip 2476 (setq text-tooltip
@@ -2468,12 +2483,18 @@ is copied instead of being cut."
2468 value-selection)))) 2483 value-selection))))
2469 2484
2470 ;; Check if selected text is read-only. 2485 ;; Check if selected text is read-only.
2471 (setq text-from-read-only (or text-from-read-only 2486 (setq text-from-read-only
2472 (get-text-property start 'read-only) 2487 (or text-from-read-only
2473 (not (equal 2488 (get-text-property start 'read-only)
2474 (next-single-char-property-change 2489 (get-text-property end 'read-only)
2475 start 'read-only nil end) 2490 (catch 'loop
2476 end))))) 2491 (dolist (bound (region-bounds))
2492 (unless (equal
2493 (next-single-char-property-change
2494 (car bound) 'read-only nil (cdr bound))
2495 (cdr bound))
2496 (throw 'loop t)))))))
2497
2477 (setq window-to-paste (posn-window (event-end event))) 2498 (setq window-to-paste (posn-window (event-end event)))
2478 (setq point-to-paste (posn-point (event-end event))) 2499 (setq point-to-paste (posn-point (event-end event)))
2479 ;; Set nil when target buffer is minibuffer. 2500 ;; Set nil when target buffer is minibuffer.
@@ -2499,13 +2520,34 @@ is copied instead of being cut."
2499 ;; the original region. When modifier is pressed, the 2520 ;; the original region. When modifier is pressed, the
2500 ;; text will be inserted to inside of the original 2521 ;; text will be inserted to inside of the original
2501 ;; region. 2522 ;; region.
2523 ;;
2524 ;; If the region is rectangular, check if the newly inserted
2525 ;; rectangular text would intersect the already selected
2526 ;; region. If it would, then set "drag-but-negligible" to t.
2527 ;; As a special case, allow dragging the region freely anywhere
2528 ;; to the left, as this will never trigger its contents to be
2529 ;; inserted into the overlays tracking it.
2502 (setq drag-but-negligible 2530 (setq drag-but-negligible
2503 (and (eq (overlay-buffer mouse-drag-and-drop-overlay) 2531 (and (eq (overlay-buffer (car mouse-drag-and-drop-overlays))
2504 buffer-to-paste) 2532 buffer-to-paste)
2505 (<= (overlay-start mouse-drag-and-drop-overlay) 2533 (if region-noncontiguous
2506 point-to-paste) 2534 (let ((size (cons region-width region-height))
2507 (<= point-to-paste 2535 (start-coordinates
2508 (overlay-end mouse-drag-and-drop-overlay))))) 2536 (rectangle-position-as-coordinates start))
2537 (point-to-paste-coordinates
2538 (rectangle-position-as-coordinates
2539 point-to-paste)))
2540 (and (rectangle-intersect-p
2541 start-coordinates size
2542 point-to-paste-coordinates size)
2543 (not (<= (car point-to-paste-coordinates)
2544 (car start-coordinates)))))
2545 (and (<= (overlay-start
2546 (car mouse-drag-and-drop-overlays))
2547 point-to-paste)
2548 (<= point-to-paste
2549 (overlay-end
2550 (car mouse-drag-and-drop-overlays))))))))
2509 2551
2510 ;; Show a tooltip. 2552 ;; Show a tooltip.
2511 (if mouse-drag-and-drop-region-show-tooltip 2553 (if mouse-drag-and-drop-region-show-tooltip
@@ -2524,8 +2566,9 @@ is copied instead of being cut."
2524 (t 2566 (t
2525 'bar))) 2567 'bar)))
2526 (when cursor-in-text-area 2568 (when cursor-in-text-area
2527 (overlay-put mouse-drag-and-drop-overlay 2569 (dolist (overlay mouse-drag-and-drop-overlays)
2528 'face 'mouse-drag-and-drop-region) 2570 (overlay-put overlay
2571 'face 'mouse-drag-and-drop-region))
2529 (deactivate-mark) ; Maintain region in other window. 2572 (deactivate-mark) ; Maintain region in other window.
2530 (mouse-set-point event))))) 2573 (mouse-set-point event)))))
2531 2574
@@ -2581,7 +2624,9 @@ is copied instead of being cut."
2581 (select-window window) 2624 (select-window window)
2582 (goto-char point) 2625 (goto-char point)
2583 (setq deactivate-mark nil) 2626 (setq deactivate-mark nil)
2584 (activate-mark)) 2627 (activate-mark)
2628 (when region-noncontiguous
2629 (rectangle-mark-mode)))
2585 ;; Modify buffers. 2630 ;; Modify buffers.
2586 (t 2631 (t
2587 ;; * DESTINATION BUFFER:: 2632 ;; * DESTINATION BUFFER::
@@ -2590,11 +2635,17 @@ is copied instead of being cut."
2590 (setq window-exempt window-to-paste) 2635 (setq window-exempt window-to-paste)
2591 (goto-char point-to-paste) 2636 (goto-char point-to-paste)
2592 (push-mark) 2637 (push-mark)
2593 (insert value-selection) 2638
2639 (if region-noncontiguous
2640 (insert-rectangle (split-string value-selection "\n"))
2641 (insert value-selection))
2642
2594 ;; On success, set the text as region on destination buffer. 2643 ;; On success, set the text as region on destination buffer.
2595 (when (not (equal (mark) (point))) 2644 (when (not (equal (mark) (point)))
2596 (setq deactivate-mark nil) 2645 (setq deactivate-mark nil)
2597 (activate-mark)) 2646 (activate-mark)
2647 (when region-noncontiguous
2648 (rectangle-mark-mode)))
2598 2649
2599 ;; * SOURCE BUFFER:: 2650 ;; * SOURCE BUFFER::
2600 ;; Set back the original text as region or delete the original 2651 ;; Set back the original text as region or delete the original
@@ -2604,8 +2655,9 @@ is copied instead of being cut."
2604 ;; remove the original text. 2655 ;; remove the original text.
2605 (when no-modifier-on-drop 2656 (when no-modifier-on-drop
2606 (let (deactivate-mark) 2657 (let (deactivate-mark)
2607 (delete-region (overlay-start mouse-drag-and-drop-overlay) 2658 (dolist (overlay mouse-drag-and-drop-overlays)
2608 (overlay-end mouse-drag-and-drop-overlay)))) 2659 (delete-region (overlay-start overlay)
2660 (overlay-end overlay)))))
2609 ;; When source buffer and destination buffer are different, 2661 ;; When source buffer and destination buffer are different,
2610 ;; keep (set back the original text as region) or remove the 2662 ;; keep (set back the original text as region) or remove the
2611 ;; original text. 2663 ;; original text.
@@ -2615,15 +2667,17 @@ is copied instead of being cut."
2615 (if mouse-drag-and-drop-region-cut-when-buffers-differ 2667 (if mouse-drag-and-drop-region-cut-when-buffers-differ
2616 ;; Remove the dragged text from source buffer like 2668 ;; Remove the dragged text from source buffer like
2617 ;; operation `cut'. 2669 ;; operation `cut'.
2618 (delete-region (overlay-start mouse-drag-and-drop-overlay) 2670 (dolist (overlay mouse-drag-and-drop-overlays)
2619 (overlay-end mouse-drag-and-drop-overlay)) 2671 (delete-region (overlay-start overlay)
2672 (overlay-end overlay)))
2620 ;; Set back the dragged text as region on source buffer 2673 ;; Set back the dragged text as region on source buffer
2621 ;; like operation `copy'. 2674 ;; like operation `copy'.
2622 (activate-mark)) 2675 (activate-mark))
2623 (select-window window-to-paste)))))) 2676 (select-window window-to-paste))))))
2624 2677
2625 ;; Clean up. 2678 ;; Clean up.
2626 (delete-overlay mouse-drag-and-drop-overlay) 2679 (dolist (overlay mouse-drag-and-drop-overlays)
2680 (delete-overlay overlay))
2627 2681
2628 ;; Restore old states but for the window where the drop 2682 ;; Restore old states but for the window where the drop
2629 ;; occurred. Restore cursor types for all windows. 2683 ;; occurred. Restore cursor types for all windows.
diff --git a/lisp/rect.el b/lisp/rect.el
index 8ccf051ee18..48db4ffd8f4 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -167,6 +167,37 @@ The final point after the last operation will be returned."
167 (<= (point) endpt)))) 167 (<= (point) endpt))))
168 final-point))) 168 final-point)))
169 169
170(defun rectangle-position-as-coordinates (position)
171 "Return cons of the column and line values of POSITION.
172POSITION specifies a position of the current buffer. The value
173returned is a cons of the current column of POSITION and its line
174number."
175 (save-excursion
176 (goto-char position)
177 (let ((col (current-column))
178 (line (1- (line-number-at-pos))))
179 (cons col line))))
180
181(defun rectangle-intersect-p (pos1 size1 pos2 size2)
182 "Return non-nil if two rectangles intersect.
183POS1 and POS2 specify the positions of the upper-left corners of
184the first and second rectangle as conses of their column and line
185values. SIZE1 and SIZE2 specify the dimensions of the first and
186second rectangle, as conses of their width and height measured in
187columns and lines."
188 (let ((x1 (car pos1))
189 (y1 (cdr pos1))
190 (x2 (car pos2))
191 (y2 (cdr pos2))
192 (w1 (car size1))
193 (h1 (cdr size1))
194 (w2 (car size2))
195 (h2 (cdr size2)))
196 (not (or (<= (+ x1 w1) x2)
197 (<= (+ x2 w2) x1)
198 (<= (+ y1 h1) y2)
199 (<= (+ y2 h2) y1)))))
200
170(defun delete-rectangle-line (startcol endcol fill) 201(defun delete-rectangle-line (startcol endcol fill)
171 (when (= (move-to-column startcol (if fill t 'coerce)) startcol) 202 (when (= (move-to-column startcol (if fill t 'coerce)) startcol)
172 (delete-region (point) 203 (delete-region (point)