mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +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
|
// DECSLRM
|
||||||
0 => if (@hasDecl(T, "setLeftAndRightMargin")) {
|
0 => if (@hasDecl(T, "setLeftAndRightMargin")) {
|
||||||
switch (action.params.len) {
|
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),
|
1 => try self.handler.setLeftAndRightMargin(action.params[0], 0),
|
||||||
2 => try self.handler.setLeftAndRightMargin(action.params[0], action.params[1]),
|
2 => try self.handler.setLeftAndRightMargin(action.params[0], action.params[1]),
|
||||||
else => log.warn("invalid DECSLRM command: {}", .{action}),
|
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) {
|
'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]) {
|
1 => switch (action.intermediates[0]) {
|
||||||
'?' => if (@hasDecl(T, "queryKittyKeyboard")) {
|
'?' => if (@hasDecl(T, "queryKittyKeyboard")) {
|
||||||
try self.handler.queryKittyKeyboard();
|
try self.handler.queryKittyKeyboard();
|
||||||
@ -1676,6 +1685,43 @@ test "stream: insert characters" {
|
|||||||
try testing.expect(!s.handler.called);
|
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" {
|
test "stream: too many csi params" {
|
||||||
const H = struct {
|
const H = struct {
|
||||||
pub fn setCursorRight(self: *@This(), v: u16) !void {
|
pub fn setCursorRight(self: *@This(), v: u16) !void {
|
||||||
|
@ -2044,6 +2044,14 @@ const StreamHandler = struct {
|
|||||||
self.terminal.setTopAndBottomMargin(top, bot);
|
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 {
|
pub fn setLeftAndRightMargin(self: *StreamHandler, left: u16, right: u16) !void {
|
||||||
self.terminal.setLeftAndRightMargin(left, right);
|
self.terminal.setLeftAndRightMargin(left, right);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user