From a373fdda0102a99cde988f87f822fc451e0f4391 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 6 Jul 2026 21:18:35 -0300 Subject: insert vs normal cursor shape (all pane types) + the tag is always insert mode. Surface.cursor grew a bar flag: the core sets it from the active pane mode (insert -> bar; normal/tty -> block) for both the modal/file cursor and the vt-tracking terminal cursor, and unconditionally for the tag cursor. tty shell: DECSCUSR via vaxis setCursorShape (beam for insert, the terminal default otherwise). gui shell: the insert cursor draws the left-eighth-block glyph in cell colors instead of the reverse-video block (ponytail: it hides the char under it; a dedicated quad if that ever matters). Tag editing: enterTagEdit goes straight to insert, Esc (or anything that exits the tag) restores the body normal mode; Enter looks / Tab executes the word at the cursor from inside the tag (tagChordText kept); the whole normal-mode tag machinery — handleTagKey motions, v/x selection, d/c/y/p, tagEnterInsert/tagDelete/tagYank/tagPaste — deleted as unreachable (~120 lines; multi-word tag execution stays the mouse middle-drag). tag.snap rewritten: INS on click, type/backspace straight in, Esc exit with the text persisting, Enter-look opens the file. Tutor documents it. Cursor SHAPE is not capturable by the harness (position only) — verify by eye: bar in insert/tags, block elsewhere, both shells. 30/30. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gui.zig | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/gui.zig') diff --git a/src/gui.zig b/src/gui.zig index 60d9501f..cc949cd1 100644 --- a/src/gui.zig +++ b/src/gui.zig @@ -1650,12 +1650,13 @@ fn renderFrame(g: *Gui, gpa: std.mem.Allocator, surface: *pardes.Surface) !void const instances: [*]CellInstance = @ptrCast(@alignCast(vptr)); const layout = fixedCellLayout(g); const cursor_idx: u32 = if (surface.cursor) |cu| @as(u32, cu.y) * surface.cols + cu.x else cells; + const cursor_bar = if (surface.cursor) |cu| cu.bar else false; var row: u16 = 0; while (row < surface.rows) : (row += 1) { var col: u16 = 0; while (col < surface.cols) : (col += 1) { const idx: u32 = @as(u32, row) * surface.cols + col; - emitInstance(g, instances, idx, col, row, layout, win_w, win_h, surface.at(col, row), idx == cursor_idx); + emitInstance(g, instances, idx, col, row, layout, win_w, win_h, surface.at(col, row), idx == cursor_idx, cursor_bar); } } c.SDL_UnmapGPUTransferBuffer(g.device, g.vxfer.?); @@ -1701,13 +1702,15 @@ fn emitInstance( win_h: f32, cell: *const pardes.Cell, is_cursor: bool, + cursor_bar: bool, ) void { // resolve the cell style to concrete fg/bg, matching the prototype's // cellKey: reverse swaps, invisible hides, dim darkens. The cursor cell - // renders as reverse (cancelling an already-reversed cell). + // renders as reverse (cancelling an already-reversed cell); an insert + // cursor keeps the cell colors and draws a bar glyph instead. var fg = fg_default; var bg = bg_default; - var reverse = is_cursor; + var reverse = is_cursor and !cursor_bar; if (!cell.default) { const st = cell.style; fg = switch (st.fg) { @@ -1737,7 +1740,10 @@ fn emitInstance( const y1 = 1.0 - ((py0 + layout.h) / win_h) * 2.0; const grapheme = cell.grapheme(); - const cp: u32 = if (cell.default or grapheme.len == 0) ' ' else firstCp(grapheme); + var cp: u32 = if (cell.default or grapheme.len == 0) ' ' else firstCp(grapheme); + // ponytail: the insert bar is the left-eighth block glyph over the cell + // (hides the char under it); a dedicated quad if that ever matters + if (is_cursor and cursor_bar) cp = 0x258F; const slot = if (cp == ' ') g.space_slot else ensureGlyph(g, cp); const aw_f: f32 = @floatFromInt(atlas_w); const ah_f: f32 = @floatFromInt(atlas_h); @@ -1944,12 +1950,13 @@ fn renderFrameGl(g: *Gui, gpa: std.mem.Allocator, surface: *pardes.Surface) !voi const win_h: f32 = @floatFromInt(sh); const layout = cellLayout(g, surface.cols, surface.rows, sw, sh); const cursor_idx: u32 = if (surface.cursor) |cu| @as(u32, cu.y) * surface.cols + cu.x else cells; + const cursor_bar = if (surface.cursor) |cu| cu.bar else false; var row: u16 = 0; while (row < surface.rows) : (row += 1) { var col: u16 = 0; while (col < surface.cols) : (col += 1) { const idx: u32 = @as(u32, row) * surface.cols + col; - emitInstance(g, g.gl_instances.ptr, idx, col, row, layout, win_w, win_h, surface.at(col, row), idx == cursor_idx); + emitInstance(g, g.gl_instances.ptr, idx, col, row, layout, win_w, win_h, surface.at(col, row), idx == cursor_idx, cursor_bar); } } if (g.atlas_dirty) uploadAtlasGl(g); -- cgit v1.3