implement device status request

This commit is contained in:
Mitchell Hashimoto
2022-05-19 20:39:12 -07:00
parent 6e86afba17
commit fd747ce274
4 changed files with 47 additions and 2 deletions

View File

@ -644,3 +644,28 @@ pub fn deviceAttributes(
else => log.warn("unimplemented device attributes req: {}", .{req}), else => log.warn("unimplemented device attributes req: {}", .{req}),
} }
} }
pub fn deviceStatusReport(
self: *Window,
req: terminal.DeviceStatusReq,
) !void {
switch (req) {
.operating_status => self.queueWrite("\x1B[0n") catch |err|
log.warn("error queueing device attr response: {}", .{err}),
.cursor_position => {
// Response always is at least 4 chars, so this leaves the
// remainder for the row/column as base-10 numbers. This
// will support a very large terminal.
var buf: [32]u8 = undefined;
const resp = try std.fmt.bufPrint(&buf, "\x1B[{};{}R", .{
self.terminal.cursor.y + 1,
self.terminal.cursor.x + 1,
});
try self.queueWrite(resp);
},
else => log.warn("unimplemented device status req: {}", .{req}),
}
}

View File

@ -49,3 +49,12 @@ pub const DeviceAttributeReq = enum {
secondary, // > secondary, // >
tertiary, // = tertiary, // =
}; };
/// The device status request type (ESC [ n).
pub const DeviceStatusReq = enum(u16) {
operating_status = 5,
cursor_position = 6,
// Non-exhaustive so that @intToEnum never fails for unsupported modes.
_,
};

View File

@ -7,6 +7,7 @@ pub const Terminal = @import("Terminal.zig");
pub const Parser = @import("Parser.zig"); pub const Parser = @import("Parser.zig");
pub const Stream = stream.Stream; pub const Stream = stream.Stream;
pub const DeviceAttributeReq = ansi.DeviceAttributeReq; pub const DeviceAttributeReq = ansi.DeviceAttributeReq;
pub const DeviceStatusReq = ansi.DeviceStatusReq;
pub const Mode = ansi.Mode; pub const Mode = ansi.Mode;
pub const EraseDisplay = csi.EraseDisplay; pub const EraseDisplay = csi.EraseDisplay;
pub const EraseLine = csi.EraseLine; pub const EraseLine = csi.EraseLine;

View File

@ -295,12 +295,22 @@ pub fn Stream(comptime Handler: type) type {
while (p.next()) |attr| try self.handler.setAttribute(attr); while (p.next()) |attr| try self.handler.setAttribute(attr);
} else log.warn("unimplemented CSI callback: {}", .{action}), } else log.warn("unimplemented CSI callback: {}", .{action}),
// CPR - Request Cursor Postion Report
// TODO: test
'n' => if (@hasDecl(T, "deviceStatusReport")) try self.handler.deviceStatusReport(
switch (action.params.len) {
1 => @intToEnum(ansi.DeviceStatusReq, action.params[0]),
else => {
log.warn("invalid erase characters command: {}", .{action});
return;
},
},
) else log.warn("unimplemented CSI callback: {}", .{action}),
// DECSTBM - Set Top and Bottom Margins // DECSTBM - Set Top and Bottom Margins
// TODO: test // TODO: test
'r' => if (@hasDecl(T, "setTopAndBottomMargin")) switch (action.params.len) { 'r' => if (@hasDecl(T, "setTopAndBottomMargin")) switch (action.params.len) {
0 => try self.handler.setTopAndBottomMargin(1, 0),
1 => try self.handler.setTopAndBottomMargin(action.params[0], 0), 1 => try self.handler.setTopAndBottomMargin(action.params[0], 0),
2 => try self.handler.setTopAndBottomMargin(action.params[0], action.params[1]),
else => log.warn("invalid DECSTBM command: {}", .{action}), else => log.warn("invalid DECSTBM command: {}", .{action}),
} else log.warn("unimplemented CSI callback: {}", .{action}), } else log.warn("unimplemented CSI callback: {}", .{action}),