mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
terminal: handle SCOSC/SCORC
Fixes #1401 SCOSC is ambiguous with regards to DECSLRM. This commit copies the logic of xterm: if left/right mode is enabled, then CSI S is always DECSLRM. But if left/right mode is disabled then CSI S empty always uses SCOSC. SCORC always works.
This commit is contained in:
@ -805,7 +805,11 @@ pub fn Stream(comptime Handler: type) type {
|
||||
// DECSLRM
|
||||
0 => if (@hasDecl(T, "setLeftAndRightMargin")) {
|
||||
switch (action.params.len) {
|
||||
0 => try self.handler.setLeftAndRightMargin(0, 0),
|
||||
// CSI S is ambiguous with zero params so we defer
|
||||
// to our handler to do the proper logic. If mode 69
|
||||
// is set, then we should invoke DECSLRM, otherwise
|
||||
// we should invoke SC.
|
||||
0 => try self.handler.setLeftAndRightMarginAmbiguous(),
|
||||
1 => try self.handler.setLeftAndRightMargin(action.params[0], 0),
|
||||
2 => try self.handler.setLeftAndRightMargin(action.params[0], action.params[1]),
|
||||
else => log.warn("invalid DECSLRM command: {}", .{action}),
|
||||
@ -865,8 +869,13 @@ pub fn Stream(comptime Handler: type) type {
|
||||
),
|
||||
},
|
||||
|
||||
// Kitty keyboard protocol
|
||||
'u' => switch (action.intermediates.len) {
|
||||
0 => if (@hasDecl(T, "restoreCursor"))
|
||||
try self.handler.restoreCursor()
|
||||
else
|
||||
log.warn("unimplemented CSI callback: {}", .{action}),
|
||||
|
||||
// Kitty keyboard protocol
|
||||
1 => switch (action.intermediates[0]) {
|
||||
'?' => if (@hasDecl(T, "queryKittyKeyboard")) {
|
||||
try self.handler.queryKittyKeyboard();
|
||||
@ -1676,6 +1685,43 @@ test "stream: insert characters" {
|
||||
try testing.expect(!s.handler.called);
|
||||
}
|
||||
|
||||
test "stream: SCOSC" {
|
||||
const H = struct {
|
||||
const Self = @This();
|
||||
called: bool = false,
|
||||
|
||||
pub fn setLeftAndRightMargin(self: *Self, left: u16, right: u16) !void {
|
||||
_ = self;
|
||||
_ = left;
|
||||
_ = right;
|
||||
@panic("bad");
|
||||
}
|
||||
|
||||
pub fn setLeftAndRightMarginAmbiguous(self: *Self) !void {
|
||||
self.called = true;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
for ("\x1B[s") |c| try s.next(c);
|
||||
try testing.expect(s.handler.called);
|
||||
}
|
||||
|
||||
test "stream: SCORC" {
|
||||
const H = struct {
|
||||
const Self = @This();
|
||||
called: bool = false,
|
||||
|
||||
pub fn restoreCursor(self: *Self) !void {
|
||||
self.called = true;
|
||||
}
|
||||
};
|
||||
|
||||
var s: Stream(H) = .{ .handler = .{} };
|
||||
for ("\x1B[u") |c| try s.next(c);
|
||||
try testing.expect(s.handler.called);
|
||||
}
|
||||
|
||||
test "stream: too many csi params" {
|
||||
const H = struct {
|
||||
pub fn setCursorRight(self: *@This(), v: u16) !void {
|
||||
|
@ -2044,6 +2044,14 @@ const StreamHandler = struct {
|
||||
self.terminal.setTopAndBottomMargin(top, bot);
|
||||
}
|
||||
|
||||
pub fn setLeftAndRightMarginAmbiguous(self: *StreamHandler) !void {
|
||||
if (self.terminal.modes.get(.enable_left_and_right_margin)) {
|
||||
try self.setLeftAndRightMargin(0, 0);
|
||||
} else {
|
||||
try self.saveCursor();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setLeftAndRightMargin(self: *StreamHandler, left: u16, right: u16) !void {
|
||||
self.terminal.setLeftAndRightMargin(left, right);
|
||||
}
|
||||
|
Reference in New Issue
Block a user