summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exec.zig14
-rw-r--r--src/ninep/cols.zig21
2 files changed, 32 insertions, 3 deletions
diff --git a/src/exec.zig b/src/exec.zig
index 8356db75..7d682d74 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -1045,9 +1045,12 @@ pub fn placeNew(p: *Pardes, from: usize, origin: ?usize, id: usize, kind: NewPan
// No pane to halve, but the column holds every pane's minimum
// with the new one's: the rows are shared out again, so what is
// refused is only what the documented arithmetic cannot hold.
- // +Errors goes wherever there is room, last column first; with
- // none, its maker says the text some other way (appendErrors).
- if (layout.shareColumn(p, f.col)) {} else if (kind == .errors) {
+ // +Errors and 9P's pane/new go wherever there is room, last
+ // column first, as acme takes rows from a window that has them
+ // before saying there are none; with none, +Errors's maker says
+ // the text some other way (appendErrors), and pane/new is
+ // refused.
+ if (layout.shareColumn(p, f.col)) {} else if (kind == .errors or kind == .fs) {
layout.removePane(p, id);
var c = p.ncol;
while (c > 0) {
@@ -1064,6 +1067,11 @@ pub fn placeNew(p: *Pardes, from: usize, origin: ?usize, id: usize, kind: NewPan
} else {
layout.insert(p, f.col, p.col_n[f.col], id);
p.unplaced.set(id);
+ // No pane anywhere can give it rows: pane/new is refused.
+ if (kind == .fs) {
+ p.panes[id].?.vweight = 0;
+ p.reportError(from, "placement", error.NoPaneRoom);
+ }
return;
}
} else {
diff --git a/src/ninep/cols.zig b/src/ninep/cols.zig
index 9185a2bc..c4ee83eb 100644
--- a/src/ninep/cols.zig
+++ b/src/ninep/cols.zig
@@ -228,6 +228,27 @@ test "New written to a column's exec makes its scratch in the session's director
try testing.expectEqualStrings("/project/src/+New", p.panes[p.active].?.file.?.path);
}
+test "pane/new takes rows from a pane in another column before refusing ENOSPC" {
+ const p = try pardes.Pardes.init(testing.allocator, .{ .tty_only = true, .cols = 160, .rows = 16 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ const first = p.panes[p.active].?.serial;
+ // A second column holding one tall pane.
+ try testing.expectEqual(tree.Status.ok, th.wr(p, @intFromEnum(tree.TopFile.ctl), "Newcol\n").reply.status);
+ const tall = try th.newPane(p);
+ const tall_col = layout.findPane(p, p.paneBySerial(tall).?).?.col;
+ const focus = @intFromEnum(tree.TopFile.focus);
+ var digits: [16]u8 = undefined;
+ // From the first column, until pane/new is refused.
+ var moved = false;
+ for (0..pardes.MAX_PANES) |_| {
+ _ = th.wr(p, focus, try std.fmt.bufPrint(&digits, "{d}\n", .{first}));
+ const made = th.newPane(p) catch break;
+ if (layout.findPane(p, p.paneBySerial(made).?).?.col == tall_col) moved = true;
+ }
+ try testing.expect(moved);
+}
+
test "a Newcol refused because the tags would not fit logs its err alone and spends no column serial" {
const p = try pardes.Pardes.init(testing.allocator, .{ .tty_only = true, .cols = 160, .rows = 14 });
defer p.deinit();