From 1912878e753ce12fdc1ac72ae2e83ddfc18df002 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 00:40:42 -0300 Subject: Let the column and workspace tags take a row for each line they hold A header is a Text like a pane's tag, so a newline typed or pasted into it should show rather than hide the lines after the first; the panes below move down to make room, as they do for a taller pane tag. Co-Authored-By: Claude Opus 5.5 --- src/mouse.zig | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'src/mouse.zig') diff --git a/src/mouse.zig b/src/mouse.zig index 33646090..4b624dca 100644 --- a/src/mouse.zig +++ b/src/mouse.zig @@ -299,12 +299,15 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { return; }; const x = if (p.header_column) |c| p.col_x[c] + TAG_TEXT_INSET else 0; - const bar = modal.lineSlice(edit.flatSurface(p, t) catch return, 0); - const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tagColumn(p, if (p.header_column != null) .column else .workspace, p.header_column orelse 0, p.pointer_tag_hit, p.header_drag, 0) orelse (mcol -| x)) + p.header_scroll)); + const text = edit.flatSurface(p, t) catch return; + const top = if (p.header_column != null) p.topBarHeight() else 0; + const line: u16 = @intCast(@min(mrow -| top, modal.lineCount(text) -| 1, (if (p.header_column != null) p.columnBarHeight() else p.topBarHeight()) -| 1)); + const bar = modal.lineSlice(text, line); + const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tagColumn(p, if (p.header_column != null) .column else .workspace, p.header_column orelse 0, p.pointer_tag_hit, p.header_drag, line) orelse (mcol -| x)) + p.header_scroll)); // the anchor stays where the press put it - t.cur_row = 0; + t.cur_row = line; t.cur_col = @intCast(at); - t.vsel.active = t.vsel.col != t.cur_col; + t.vsel.active = t.vsel.row != t.cur_row or t.vsel.col != t.cur_col; if (m.kind == .release) p.header_drag = false; return; } @@ -330,19 +333,22 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { } const t = if (column) |c| &p.col_tags[c] else &p.global_tag; const focused = p.header_focus and p.header_column == column; - const bar = modal.lineSlice(edit.flatSurface(p, t) catch return, 0); + const text = edit.flatSurface(p, t) catch return; + const line: u16 = @intCast(mrow - if (column != null) p.topBarHeight() else 0); + if (line > 0 and line >= modal.lineCount(text)) return; + const bar = modal.lineSlice(text, line); const scroll = if (focused) p.header_scroll else 0; - const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tagColumn(p, if (column != null) .column else .workspace, column orelse 0, p.pointer_tag_hit, p.header_drag, 0) orelse (mcol -| x)) + scroll)); + const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tagColumn(p, if (column != null) .column else .workspace, column orelse 0, p.pointer_tag_hit, p.header_drag, line) orelse (mcol -| x)) + scroll)); if (m.button == config.select_button) { // A clicked header is typed straight into, as a clicked tag is. if (!focused) p.enterHeader(column); t.mode = .insert; - t.cur_row = 0; + t.cur_row = line; t.cur_col = @intCast(at); - t.vsel = .{ .active = false, .row = 0, .col = @intCast(at) }; + t.vsel = .{ .active = false, .row = line, .col = @intCast(at) }; p.header_drag = true; } else { - const span = if (focused) Pardes.headerSelection(t, bar) else null; + const span = if (focused) Pardes.headerSelection(t, text, line) else null; const selected = if (span) |sp| (if (at >= sp.lo and at < sp.hi) bar[sp.lo..sp.hi] else wordAtCol(bar, at)) else -- cgit v1.3