summaryrefslogtreecommitdiff
path: root/src/mouse.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 18:56:04 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commitab806dc38ddcd74958b999fe708ae9ea63609f72 (patch)
tree467711a8175956c5726a1181aa6e34de256597a0 /src/mouse.zig
parentc4ab29bce30f427decf3e199eebecfd415714a96 (diff)
downloadpardes-ab806dc38ddcd74958b999fe708ae9ea63609f72.tar.gz
pardes-ab806dc38ddcd74958b999fe708ae9ea63609f72.zip
A mouse sweep selects a stream, as acme's does, not a rectangle
A B1, B2 or B3 drag over several lines took the same columns from every row, a block. acme's sweep is a stream (libframe/frselect.c:115-140, frselectpaint; acme text.c:881, textselect): the first row from the press to its end, the rows between whole, the last from its start to the release. edit.sweepCols says which columns of a row a sweep takes; the captured spans, the text a sweep yields (copy, chords, B2 and B3 operands, a terminal's automatic yank) and the highlight all follow it, in bodies, multi-row tags, terminals and text-rendered PDFs; a row the sweep runs through is highlighted to the edge, and rows after the first leave out the line numbers. Native PDF selection was already MuPDF's stream. No pane keeps a rectangle. exec-bigdrag's golden changes: its middle sweep now runs whole lines. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/mouse.zig')
-rw-r--r--src/mouse.zig12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/mouse.zig b/src/mouse.zig
index 22eb3270..2dcd80ed 100644
--- a/src/mouse.zig
+++ b/src/mouse.zig
@@ -691,12 +691,13 @@ fn gestureRange(p: *Pardes, id: usize, text: []const u8, on_tag: bool, operand:
const start: ?modal.Cursor = if (operand.file_word) |w|
.{ .row = @intCast(@max(0, w.row)), .col = @intCast(@max(0, w.lo)) }
else if (operand.expanded orelse operand.preview) |sel| lead: {
- // A selection's leading corner in reading order, converted the way
+ // A selection's start in reading order, converted the way
// `pointerOperand` converts the click itself.
- const top = @min(sel.r0, sel.r1) - @as(i32, pane.tag_rows);
+ const lead = edit.sweepEnds(sel)[0];
+ const top = lead[0] - @as(i32, pane.tag_rows);
if (top < 0) break :lead null;
const w = pane.wrapAt(top);
- const col = edit.paneByteAtDisplay(p, &pane.body, w.line, w.at, @min(sel.c0, sel.c1) - panes.File.gutterWidth(pane));
+ const col = edit.paneByteAtDisplay(p, &pane.body, w.line, w.at, lead[1] - panes.File.gutterWidth(pane));
break :lead .{
.row = @intCast(@max(0, w.line)),
.col = @intCast(@max(0, col)),
@@ -730,10 +731,11 @@ fn mirrorTtySelection(p: *Pardes, pane: *Pane) void {
const rows = pane.pointerSelection(gesture) orelse return;
const text = pane.rawPointerText(gesture) orelse return;
if (rows.len == 0) return;
- const endpoint = rows[if (gesture.r1 >= gesture.r0) rows.len - 1 else 0];
+ const forward = gesture.r1 > gesture.r0 or (gesture.r1 == gesture.r0 and gesture.c1 >= gesture.c0);
+ const endpoint = rows[if (forward) rows.len - 1 else 0];
const body = body_layer.bodyText(p, p.scratch.allocator(), pane) catch return;
const line = modal.lineSlice(body, @intCast(@max(0, endpoint.row - panes.Terminal.gridOffset(pane))));
- const byte = if (gesture.c1 >= gesture.c0) modal.prevGrapheme(line, @min(endpoint.hi, line.len)) else endpoint.lo;
+ const byte = if (forward) modal.prevGrapheme(line, @min(endpoint.hi, line.len)) else endpoint.lo;
pane.body.cur_row = pane.surfRow(endpoint.row);
var shown = std.mem.trimEnd(u8, line[@min(endpoint.prompt_bytes, line.len)..], " \t");
if (pane.ovl) |overlay| {