mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
save and restore cursor
This commit is contained in:
@ -781,3 +781,11 @@ pub fn tabClear(self: *Window, cmd: terminal.TabClear) !void {
|
|||||||
pub fn tabSet(self: *Window) !void {
|
pub fn tabSet(self: *Window) !void {
|
||||||
self.terminal.tabSet();
|
self.terminal.tabSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn saveCursor(self: *Window) !void {
|
||||||
|
self.terminal.saveCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restoreCursor(self: *Window) !void {
|
||||||
|
self.terminal.restoreCursor();
|
||||||
|
}
|
||||||
|
@ -28,6 +28,9 @@ screen: Screen,
|
|||||||
/// Cursor position.
|
/// Cursor position.
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
|
|
||||||
|
/// Saved cursor saved with DECSC (ESC 7).
|
||||||
|
saved_cursor: Cursor,
|
||||||
|
|
||||||
/// Where the tabstops are.
|
/// Where the tabstops are.
|
||||||
tabstops: Tabstops,
|
tabstops: Tabstops,
|
||||||
|
|
||||||
@ -53,8 +56,8 @@ const ScrollingRegion = struct {
|
|||||||
/// Cursor represents the cursor state.
|
/// Cursor represents the cursor state.
|
||||||
const Cursor = struct {
|
const Cursor = struct {
|
||||||
// x, y where the cursor currently exists (0-indexed).
|
// x, y where the cursor currently exists (0-indexed).
|
||||||
x: usize,
|
x: usize = 0,
|
||||||
y: usize,
|
y: usize = 0,
|
||||||
|
|
||||||
// pen is the current cell styling to apply to new cells.
|
// pen is the current cell styling to apply to new cells.
|
||||||
pen: Screen.Cell = .{ .char = 0 },
|
pen: Screen.Cell = .{ .char = 0 },
|
||||||
@ -66,7 +69,8 @@ pub fn init(alloc: Allocator, cols: usize, rows: usize) !Terminal {
|
|||||||
.cols = cols,
|
.cols = cols,
|
||||||
.rows = rows,
|
.rows = rows,
|
||||||
.screen = try Screen.init(alloc, rows, cols),
|
.screen = try Screen.init(alloc, rows, cols),
|
||||||
.cursor = .{ .x = 0, .y = 0 },
|
.cursor = .{},
|
||||||
|
.saved_cursor = .{},
|
||||||
.tabstops = try Tabstops.init(alloc, cols, TABSTOP_INTERVAL),
|
.tabstops = try Tabstops.init(alloc, cols, TABSTOP_INTERVAL),
|
||||||
.scrolling_region = .{
|
.scrolling_region = .{
|
||||||
.top = 0,
|
.top = 0,
|
||||||
@ -119,6 +123,23 @@ pub fn plainString(self: Terminal, alloc: Allocator) ![]const u8 {
|
|||||||
return try self.screen.testString(alloc);
|
return try self.screen.testString(alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Save cursor position and further state.
|
||||||
|
///
|
||||||
|
/// The primary and alternate screen have distinct save state. One saved state
|
||||||
|
/// is kept per screen (main / alternative). If for the current screen state
|
||||||
|
/// was already saved it is overwritten.
|
||||||
|
pub fn saveCursor(self: *Terminal) void {
|
||||||
|
self.saved_cursor = self.cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restore cursor position and other state.
|
||||||
|
///
|
||||||
|
/// The primary and alternate screen have distinct save state.
|
||||||
|
/// If no save was done before values are reset to their initial values.
|
||||||
|
pub fn restoreCursor(self: *Terminal) void {
|
||||||
|
self.cursor = self.saved_cursor;
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: test
|
/// TODO: test
|
||||||
pub fn setAttribute(self: *Terminal, attr: sgr.Attribute) !void {
|
pub fn setAttribute(self: *Terminal, attr: sgr.Attribute) !void {
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
|
@ -379,8 +379,23 @@ pub fn Stream(comptime Handler: type) type {
|
|||||||
action: Parser.Action.ESC,
|
action: Parser.Action.ESC,
|
||||||
) !void {
|
) !void {
|
||||||
switch (action.final) {
|
switch (action.final) {
|
||||||
|
// DECSC - Save Cursor
|
||||||
|
'7' => if (@hasDecl(T, "saveCursor")) switch (action.intermediates.len) {
|
||||||
|
0 => try self.handler.saveCursor(),
|
||||||
|
else => {
|
||||||
|
log.warn("invalid command: {}", .{action});
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
} else log.warn("unimplemented ESC callback: {}", .{action}),
|
||||||
|
|
||||||
'8' => blk: {
|
'8' => blk: {
|
||||||
switch (action.intermediates.len) {
|
switch (action.intermediates.len) {
|
||||||
|
// DECRC - Restore Cursor
|
||||||
|
0 => if (@hasDecl(T, "restoreCursor")) {
|
||||||
|
try self.handler.restoreCursor();
|
||||||
|
break :blk {};
|
||||||
|
} else log.warn("unimplemented restore cursor callback: {}", .{action}),
|
||||||
|
|
||||||
1 => switch (action.intermediates[0]) {
|
1 => switch (action.intermediates[0]) {
|
||||||
// DECALN - Fill Screen with E
|
// DECALN - Fill Screen with E
|
||||||
'#' => if (@hasDecl(T, "decaln")) {
|
'#' => if (@hasDecl(T, "decaln")) {
|
||||||
|
Reference in New Issue
Block a user