summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/pane.zig44
1 files changed, 29 insertions, 15 deletions
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index 7e9cf7e7..282ae473 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -15,6 +15,7 @@ const addressing = @import("addr.zig");
const ctl = @import("ctl.zig");
const pty = @import("pty.zig");
const screen = @import("screen.zig");
+const limits = @import("../memory.zig").limits;
const Pardes = pardes.Pardes;
const Pane = pardes.Pane;
@@ -384,7 +385,7 @@ pub fn write(p: *Pardes, req: Req, id: usize, pane: *Pane, file: PaneFile) Reply
return switch (file) {
.name => writeName(p, req, id, pane),
.body => writeBody(p, req, id, pane),
- .tag => writeTag(p, req, pane),
+ .tag => writeTag(req, pane),
.ctl => ctl.writePane(p, req, pane),
.addr, .dot, .limit => writeRange(req, pane, file),
.data, .xdata => writeData(p, req, pane),
@@ -417,15 +418,15 @@ fn writeBody(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply {
return .{ .tag = req.tag, .written = @intCast(take) };
}
-fn writeTag(p: *Pardes, req: Req, pane: *Pane) Reply {
+fn writeTag(req: Req, pane: *Pane) Reply {
if (req.data.len == 0) return .{ .tag = req.tag, .written = 0 };
- p.seedTail(pane);
- const room = pane.tag_tail.len - pane.tag_tail_len;
+ // The tag's own text grows by what is written, newlines and all: a tag
+ // is a text like any other (acme's tag file appends the same way).
+ const had = Pardes.curTail(pane).len;
+ const room = limits.max_tag_tail -| had;
if (room == 0) return Reply.fail(req.tag, E.NOSPC);
const take = wholeUtf8(req.data[0..@min(req.data.len, room)]);
- @memcpy(pane.tag_tail[pane.tag_tail_len..][0..take], req.data[0..take]);
- pane.tag_tail_len += take;
- pane.tag_init = true;
+ pane.appendTag(req.data[0..take]) catch return Reply.fail(req.tag, E.NOMEM);
return .{ .tag = req.tag, .written = @intCast(take) };
}
@@ -553,8 +554,8 @@ pub fn nameBuffer(p: *Pardes, id: usize, full: []const u8, preserve_tag: bool) !
f.output = null;
pane.clearCwd();
if (!preserve_tag) {
- pane.tag_init = false;
- pane.tag_tail_len = 0;
+ if (pane.tag.own) |own| p.gpa.free(own);
+ pane.tag.own = null;
}
f.saved_revision = f.revision -% 1;
f.watch_after_save = fs.localPath(full) != null;
@@ -606,8 +607,13 @@ pub fn truncate(p: *Pardes, pane: *Pane, file: PaneFile) tree.Status {
setDot(pane, .{});
},
.tag => {
- pane.tag_tail_len = 0;
- pane.tag_init = true;
+ const empty = p.gpa.alloc(u8, 0) catch return .err;
+ if (pane.tag.own) |own| p.gpa.free(own);
+ pane.tag.own = empty;
+ pane.tag.cur_row = 0;
+ pane.tag.cur_col = 0;
+ pane.tag.vsel.active = false;
+ pane.tag.nsel = 0;
},
.addr => pf.addr = .{},
.limit => pf.limit = null,
@@ -740,12 +746,20 @@ test "tag reads the whole tag and writes append to the editable tail" {
const before = rd(p, node, 0, 4096).bytes.len;
const w = wr(p, node, " Mine");
try testing.expectEqual(@as(u32, 5), w.reply.written);
- try testing.expect(std.mem.endsWith(u8, pane.tag_tail[0..pane.tag_tail_len], " Mine"));
+ try testing.expect(std.mem.endsWith(u8, Pardes.curTail(pane), " Mine"));
const after = rd(p, node, 0, 4096);
try testing.expectEqual(before + 5, after.bytes.len);
try testing.expect(std.mem.endsWith(u8, after.bytes, " Mine"));
- pane.tag_tail_len = pane.tag_tail.len;
+ // A tag is a text like the body: a newline written to it stays one, and
+ // the tag reads back taller by it.
+ try testing.expectEqual(@as(u32, 10), wr(p, node, "\nNext Line").reply.written);
+ try testing.expect(std.mem.endsWith(u8, Pardes.curTail(pane), " Mine\nNext Line"));
+ try testing.expect(std.mem.endsWith(u8, rd(p, node, 0, 4096).bytes, " Mine\nNext Line"));
+
+ if (pane.tag.own) |own| p.gpa.free(own);
+ pane.tag.own = try p.gpa.alloc(u8, limits.max_tag_tail);
+ @memset(pane.tag.own.?, 'x');
try testing.expectEqual(E.NOSPC, wr(p, node, "x").errno());
}
@@ -873,10 +887,10 @@ test "truncating the tag clears its editable tail" {
const pane = p.panes[0].?;
const tag = Node.of(pane.serial, .tag);
_ = wr(p, tag, " Mine");
- try testing.expect(pane.tag_tail_len > 0);
+ try testing.expect(Pardes.curTail(pane).len > 0);
const cleared = call(p, .{ .tag = 1, .op = .setattr, .node = tag, .truncate = true });
try testing.expectEqual(Status.ok, cleared.reply.status);
- try testing.expectEqual(@as(usize, 0), pane.tag_tail_len);
+ try testing.expectEqualStrings("", pane.tag.own.?);
try testing.expect(std.mem.indexOf(u8, rd(p, tag, 0, 4096).bytes, " Mine") == null);
}