summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/ctl.zig30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 378dd844..26a18a12 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -472,6 +472,14 @@ pub fn writeRoot(p: *Pardes, req: Req) Reply {
var it = Messages.init(p, req.data);
while (it.next()) |line| {
if (line.len == 0) continue;
+ if (std.mem.startsWith(u8, line, "size ") or std.mem.eql(u8, line, "size")) {
+ const size = sizeOf(line) orelse return refuse(p, req, "size takes <cols> <rows>", line);
+ // A frontend's window is the size; only a session none is
+ // attached to (--detach, unattended) takes one written.
+ if (!p.unattended) return refuse(p, req, "size: a frontend is attached and owns the size", line);
+ if (apply) p.update(.{ .resize = .{ .cols = size[0], .rows = size[1] } });
+ continue;
+ }
if (!apply) {
if (checkBuiltin(p, req, line, .session)) |refusal| return refusal;
continue;
@@ -485,6 +493,15 @@ pub fn writeRoot(p: *Pardes, req: Req) Reply {
return .{ .tag = req.tag, .written = @intCast(req.data.len) };
}
+/// `size <cols> <rows>`, each at least a few cells and at most 4096.
+fn sizeOf(line: []const u8) ?[2]u16 {
+ var it = std.mem.tokenizeAny(u8, line["size".len..], " \t");
+ const cols = std.fmt.parseInt(u16, it.next() orelse return null, 10) catch return null;
+ const rows = std.fmt.parseInt(u16, it.next() orelse return null, 10) catch return null;
+ if (it.next() != null or cols < 20 or rows < 4 or cols > 4096 or rows > 4096) return null;
+ return .{ cols, rows };
+}
+
// ---- /commands ----
/// Every builtin the registry holds, one a line: its word, `arg` when it
@@ -1460,3 +1477,16 @@ test "Edit's p and = never fail for want of room for +Errors: the text is logged
for (p.panes) |slot| count += @intFromBool(slot != null);
try testing.expectEqual(@as(usize, 1), count); // the +Errors that had no room is gone
}
+
+test "size sets the screen of a session no frontend is attached to, and only of one" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ const root_ctl = @intFromEnum(tree.TopFile.ctl);
+ try testing.expectEqual(E.INVAL, wr(p, root_ctl, "size 120 40\n").errno()); // a frontend's
+ p.unattended = true;
+ try testing.expectEqual(Status.ok, wr(p, root_ctl, "size 120 40\n").reply.status);
+ try testing.expectEqual(@as(u16, 120), p.screen_w);
+ try testing.expectEqual(@as(u16, 40), p.screen_h);
+ try testing.expectEqual(E.INVAL, wr(p, root_ctl, "size 120\n").errno());
+ try testing.expectEqual(E.INVAL, wr(p, root_ctl, "size 5 2\n").errno());
+}