ScreenSet
parent
368f4f565a
commit
3aff5f0aff
|
|
@ -186,7 +186,7 @@ const Mouse = struct {
|
||||||
/// The point at which the left mouse click happened. This is in screen
|
/// The point at which the left mouse click happened. This is in screen
|
||||||
/// coordinates so that scrolling preserves the location.
|
/// coordinates so that scrolling preserves the location.
|
||||||
left_click_pin: ?*terminal.Pin = null,
|
left_click_pin: ?*terminal.Pin = null,
|
||||||
left_click_screen: terminal.ScreenType = .primary,
|
left_click_screen: terminal.ScreenSet.Key = .primary,
|
||||||
|
|
||||||
/// The starting xpos/ypos of the left click. Note that if scrolling occurs,
|
/// The starting xpos/ypos of the left click. Note that if scrolling occurs,
|
||||||
/// these will point to different "cells", but the xpos/ypos will stay
|
/// these will point to different "cells", but the xpos/ypos will stay
|
||||||
|
|
@ -1065,7 +1065,7 @@ fn selectionScrollTick(self: *Surface) !void {
|
||||||
|
|
||||||
// If our screen changed while this is happening, we stop our
|
// If our screen changed while this is happening, we stop our
|
||||||
// selection scroll.
|
// selection scroll.
|
||||||
if (self.mouse.left_click_screen != t.active_screen) {
|
if (self.mouse.left_click_screen != t.screens.active_key) {
|
||||||
self.io.queueMessage(
|
self.io.queueMessage(
|
||||||
.{ .selection_scroll = false },
|
.{ .selection_scroll = false },
|
||||||
.locked,
|
.locked,
|
||||||
|
|
@ -1703,7 +1703,7 @@ pub fn dumpTextLocked(
|
||||||
// If our bottom right pin is before the viewport, then we can't
|
// If our bottom right pin is before the viewport, then we can't
|
||||||
// possibly have this text be within the viewport.
|
// possibly have this text be within the viewport.
|
||||||
const vp_tl_pin = self.io.terminal.screen.pages.getTopLeft(.viewport);
|
const vp_tl_pin = self.io.terminal.screen.pages.getTopLeft(.viewport);
|
||||||
const br_pin = sel.bottomRight(&self.io.terminal.screen);
|
const br_pin = sel.bottomRight(self.io.terminal.screen);
|
||||||
if (br_pin.before(vp_tl_pin)) break :viewport null;
|
if (br_pin.before(vp_tl_pin)) break :viewport null;
|
||||||
|
|
||||||
// If our top-left pin is after the viewport, then we can't possibly
|
// If our top-left pin is after the viewport, then we can't possibly
|
||||||
|
|
@ -1714,7 +1714,7 @@ pub fn dumpTextLocked(
|
||||||
log.warn("viewport bottom-right pin not found, bug?", .{});
|
log.warn("viewport bottom-right pin not found, bug?", .{});
|
||||||
break :viewport null;
|
break :viewport null;
|
||||||
};
|
};
|
||||||
const tl_pin = sel.topLeft(&self.io.terminal.screen);
|
const tl_pin = sel.topLeft(self.io.terminal.screen);
|
||||||
if (vp_br_pin.before(tl_pin)) break :viewport null;
|
if (vp_br_pin.before(tl_pin)) break :viewport null;
|
||||||
|
|
||||||
// We established that our top-left somewhere before the viewport
|
// We established that our top-left somewhere before the viewport
|
||||||
|
|
@ -1984,7 +1984,7 @@ fn copySelectionToClipboards(
|
||||||
var contents: std.ArrayList(apprt.ClipboardContent) = .empty;
|
var contents: std.ArrayList(apprt.ClipboardContent) = .empty;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
.plain => {
|
.plain => {
|
||||||
var formatter: ScreenFormatter = .init(&self.io.terminal.screen, opts);
|
var formatter: ScreenFormatter = .init(self.io.terminal.screen, opts);
|
||||||
formatter.content = .{ .selection = sel };
|
formatter.content = .{ .selection = sel };
|
||||||
try formatter.format(&aw.writer);
|
try formatter.format(&aw.writer);
|
||||||
try contents.append(alloc, .{
|
try contents.append(alloc, .{
|
||||||
|
|
@ -1994,7 +1994,7 @@ fn copySelectionToClipboards(
|
||||||
},
|
},
|
||||||
|
|
||||||
.vt => {
|
.vt => {
|
||||||
var formatter: ScreenFormatter = .init(&self.io.terminal.screen, opts: {
|
var formatter: ScreenFormatter = .init(self.io.terminal.screen, opts: {
|
||||||
var copy = opts;
|
var copy = opts;
|
||||||
copy.emit = .vt;
|
copy.emit = .vt;
|
||||||
break :opts copy;
|
break :opts copy;
|
||||||
|
|
@ -2011,7 +2011,7 @@ fn copySelectionToClipboards(
|
||||||
},
|
},
|
||||||
|
|
||||||
.html => {
|
.html => {
|
||||||
var formatter: ScreenFormatter = .init(&self.io.terminal.screen, opts: {
|
var formatter: ScreenFormatter = .init(self.io.terminal.screen, opts: {
|
||||||
var copy = opts;
|
var copy = opts;
|
||||||
copy.emit = .html;
|
copy.emit = .html;
|
||||||
break :opts copy;
|
break :opts copy;
|
||||||
|
|
@ -2029,7 +2029,7 @@ fn copySelectionToClipboards(
|
||||||
|
|
||||||
.mixed => {
|
.mixed => {
|
||||||
// First, generate plain text with codepoint mappings applied
|
// First, generate plain text with codepoint mappings applied
|
||||||
var formatter: ScreenFormatter = .init(&self.io.terminal.screen, opts);
|
var formatter: ScreenFormatter = .init(self.io.terminal.screen, opts);
|
||||||
formatter.content = .{ .selection = sel };
|
formatter.content = .{ .selection = sel };
|
||||||
try formatter.format(&aw.writer);
|
try formatter.format(&aw.writer);
|
||||||
try contents.append(alloc, .{
|
try contents.append(alloc, .{
|
||||||
|
|
@ -2039,7 +2039,7 @@ fn copySelectionToClipboards(
|
||||||
|
|
||||||
assert(aw.written().len == 0);
|
assert(aw.written().len == 0);
|
||||||
// Second, generate HTML without codepoint mappings
|
// Second, generate HTML without codepoint mappings
|
||||||
formatter = .init(&self.io.terminal.screen, opts: {
|
formatter = .init(self.io.terminal.screen, opts: {
|
||||||
var copy = opts;
|
var copy = opts;
|
||||||
copy.emit = .html;
|
copy.emit = .html;
|
||||||
|
|
||||||
|
|
@ -3098,7 +3098,7 @@ pub fn scrollCallback(
|
||||||
// we convert to cursor keys. This only happens if we're:
|
// we convert to cursor keys. This only happens if we're:
|
||||||
// (1) alt screen (2) no explicit mouse reporting and (3) alt
|
// (1) alt screen (2) no explicit mouse reporting and (3) alt
|
||||||
// scroll mode enabled.
|
// scroll mode enabled.
|
||||||
if (self.io.terminal.active_screen == .alternate and
|
if (self.io.terminal.screens.active_key == .alternate and
|
||||||
self.io.terminal.flags.mouse_event == .none and
|
self.io.terminal.flags.mouse_event == .none and
|
||||||
self.io.terminal.modes.get(.mouse_alternate_scroll))
|
self.io.terminal.modes.get(.mouse_alternate_scroll))
|
||||||
{
|
{
|
||||||
|
|
@ -3506,7 +3506,7 @@ pub fn mouseButtonCallback(
|
||||||
{
|
{
|
||||||
const pos = try self.rt_surface.getCursorPos();
|
const pos = try self.rt_surface.getCursorPos();
|
||||||
const point = self.posToViewport(pos.x, pos.y);
|
const point = self.posToViewport(pos.x, pos.y);
|
||||||
const screen = &self.renderer_state.terminal.screen;
|
const screen: *terminal.Screen = self.renderer_state.terminal.screen;
|
||||||
const p = screen.pages.pin(.{ .viewport = point }) orelse {
|
const p = screen.pages.pin(.{ .viewport = point }) orelse {
|
||||||
log.warn("failed to get pin for clicked point", .{});
|
log.warn("failed to get pin for clicked point", .{});
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -3681,7 +3681,7 @@ pub fn mouseButtonCallback(
|
||||||
self.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer self.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
const t: *terminal.Terminal = self.renderer_state.terminal;
|
const t: *terminal.Terminal = self.renderer_state.terminal;
|
||||||
const screen = &self.renderer_state.terminal.screen;
|
const screen: *terminal.Screen = self.renderer_state.terminal.screen;
|
||||||
|
|
||||||
const pos = try self.rt_surface.getCursorPos();
|
const pos = try self.rt_surface.getCursorPos();
|
||||||
const pin = pin: {
|
const pin = pin: {
|
||||||
|
|
@ -3717,14 +3717,15 @@ pub fn mouseButtonCallback(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.mouse.left_click_pin) |prev| {
|
if (self.mouse.left_click_pin) |prev| {
|
||||||
const pin_screen = t.getScreen(self.mouse.left_click_screen);
|
if (t.screens.get(self.mouse.left_click_screen)) |pin_screen| {
|
||||||
pin_screen.pages.untrackPin(prev);
|
pin_screen.pages.untrackPin(prev);
|
||||||
|
}
|
||||||
self.mouse.left_click_pin = null;
|
self.mouse.left_click_pin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store it
|
// Store it
|
||||||
self.mouse.left_click_pin = pin;
|
self.mouse.left_click_pin = pin;
|
||||||
self.mouse.left_click_screen = t.active_screen;
|
self.mouse.left_click_screen = t.screens.active_key;
|
||||||
self.mouse.left_click_xpos = pos.x;
|
self.mouse.left_click_xpos = pos.x;
|
||||||
self.mouse.left_click_ypos = pos.y;
|
self.mouse.left_click_ypos = pos.y;
|
||||||
|
|
||||||
|
|
@ -3808,7 +3809,7 @@ pub fn mouseButtonCallback(
|
||||||
defer self.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
|
|
||||||
// Get our viewport pin
|
// Get our viewport pin
|
||||||
const screen = &self.renderer_state.terminal.screen;
|
const screen: *terminal.Screen = self.renderer_state.terminal.screen;
|
||||||
const pin = pin: {
|
const pin = pin: {
|
||||||
const pos = try self.rt_surface.getCursorPos();
|
const pos = try self.rt_surface.getCursorPos();
|
||||||
const pt_viewport = self.posToViewport(pos.x, pos.y);
|
const pt_viewport = self.posToViewport(pos.x, pos.y);
|
||||||
|
|
@ -3911,7 +3912,7 @@ fn clickMoveCursor(self: *Surface, to: terminal.Pin) !void {
|
||||||
// Click to move cursor only works on the primary screen where prompts
|
// Click to move cursor only works on the primary screen where prompts
|
||||||
// exist. This means that alt screen multiplexers like tmux will not
|
// exist. This means that alt screen multiplexers like tmux will not
|
||||||
// support this feature. It is just too messy.
|
// support this feature. It is just too messy.
|
||||||
if (t.active_screen != .primary) return;
|
if (t.screens.active_key != .primary) return;
|
||||||
|
|
||||||
// This flag is only set if we've seen at least one semantic prompt
|
// This flag is only set if we've seen at least one semantic prompt
|
||||||
// OSC sequence. If we've never seen that sequence, we can't possibly
|
// OSC sequence. If we've never seen that sequence, we can't possibly
|
||||||
|
|
@ -3964,7 +3965,7 @@ fn linkAtPos(
|
||||||
terminal.Selection,
|
terminal.Selection,
|
||||||
} {
|
} {
|
||||||
// Convert our cursor position to a screen point.
|
// Convert our cursor position to a screen point.
|
||||||
const screen = &self.renderer_state.terminal.screen;
|
const screen: *terminal.Screen = self.renderer_state.terminal.screen;
|
||||||
const mouse_pin: terminal.Pin = mouse_pin: {
|
const mouse_pin: terminal.Pin = mouse_pin: {
|
||||||
const point = self.posToViewport(pos.x, pos.y);
|
const point = self.posToViewport(pos.x, pos.y);
|
||||||
const pin = screen.pages.pin(.{ .viewport = point }) orelse {
|
const pin = screen.pages.pin(.{ .viewport = point }) orelse {
|
||||||
|
|
@ -4237,7 +4238,7 @@ pub fn cursorPosCallback(
|
||||||
insp.mouse.last_xpos = pos.x;
|
insp.mouse.last_xpos = pos.x;
|
||||||
insp.mouse.last_ypos = pos.y;
|
insp.mouse.last_ypos = pos.y;
|
||||||
|
|
||||||
const screen = &self.renderer_state.terminal.screen;
|
const screen: *terminal.Screen = self.renderer_state.terminal.screen;
|
||||||
insp.mouse.last_point = screen.pages.pin(.{ .viewport = .{
|
insp.mouse.last_point = screen.pages.pin(.{ .viewport = .{
|
||||||
.x = pos_vp.x,
|
.x = pos_vp.x,
|
||||||
.y = pos_vp.y,
|
.y = pos_vp.y,
|
||||||
|
|
@ -4303,7 +4304,7 @@ pub fn cursorPosCallback(
|
||||||
// invalidate our pin or mouse state because if the screen switches
|
// invalidate our pin or mouse state because if the screen switches
|
||||||
// back then we can continue our selection.
|
// back then we can continue our selection.
|
||||||
const t: *terminal.Terminal = self.renderer_state.terminal;
|
const t: *terminal.Terminal = self.renderer_state.terminal;
|
||||||
if (self.mouse.left_click_screen != t.active_screen) break :select;
|
if (self.mouse.left_click_screen != t.screens.active_key) break :select;
|
||||||
|
|
||||||
// All roads lead to requiring a re-render at this point.
|
// All roads lead to requiring a re-render at this point.
|
||||||
try self.queueRender();
|
try self.queueRender();
|
||||||
|
|
@ -4328,7 +4329,7 @@ pub fn cursorPosCallback(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to points
|
// Convert to points
|
||||||
const screen = &t.screen;
|
const screen: *terminal.Screen = t.screen;
|
||||||
const pin = screen.pages.pin(.{
|
const pin = screen.pages.pin(.{
|
||||||
.viewport = .{
|
.viewport = .{
|
||||||
.x = pos_vp.x,
|
.x = pos_vp.x,
|
||||||
|
|
@ -4357,7 +4358,7 @@ fn dragLeftClickDouble(
|
||||||
self: *Surface,
|
self: *Surface,
|
||||||
drag_pin: terminal.Pin,
|
drag_pin: terminal.Pin,
|
||||||
) !void {
|
) !void {
|
||||||
const screen = &self.io.terminal.screen;
|
const screen: *terminal.Screen = self.io.terminal.screen;
|
||||||
const click_pin = self.mouse.left_click_pin.?.*;
|
const click_pin = self.mouse.left_click_pin.?.*;
|
||||||
|
|
||||||
// Get the word closest to our starting click.
|
// Get the word closest to our starting click.
|
||||||
|
|
@ -4397,7 +4398,7 @@ fn dragLeftClickTriple(
|
||||||
self: *Surface,
|
self: *Surface,
|
||||||
drag_pin: terminal.Pin,
|
drag_pin: terminal.Pin,
|
||||||
) !void {
|
) !void {
|
||||||
const screen = &self.io.terminal.screen;
|
const screen: *terminal.Screen = self.io.terminal.screen;
|
||||||
const click_pin = self.mouse.left_click_pin.?.*;
|
const click_pin = self.mouse.left_click_pin.?.*;
|
||||||
|
|
||||||
// Get the line selection under our current drag point. If there isn't a
|
// Get the line selection under our current drag point. If there isn't a
|
||||||
|
|
@ -4930,7 +4931,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||||
{
|
{
|
||||||
self.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer self.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
if (self.io.terminal.active_screen == .alternate) return false;
|
if (self.io.terminal.screens.active_key == .alternate) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.io.queueMessage(.{
|
self.io.queueMessage(.{
|
||||||
|
|
@ -4966,7 +4967,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||||
self.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer self.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
const sel = self.io.terminal.screen.selection orelse return false;
|
const sel = self.io.terminal.screen.selection orelse return false;
|
||||||
const tl = sel.topLeft(&self.io.terminal.screen);
|
const tl = sel.topLeft(self.io.terminal.screen);
|
||||||
self.io.terminal.screen.scroll(.{ .pin = tl });
|
self.io.terminal.screen.scroll(.{ .pin = tl });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5220,7 +5221,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||||
self.renderer_state.mutex.lock();
|
self.renderer_state.mutex.lock();
|
||||||
defer self.renderer_state.mutex.unlock();
|
defer self.renderer_state.mutex.unlock();
|
||||||
|
|
||||||
const screen = &self.io.terminal.screen;
|
const screen: *terminal.Screen = self.io.terminal.screen;
|
||||||
const sel = if (screen.selection) |*sel| sel else {
|
const sel = if (screen.selection) |*sel| sel else {
|
||||||
// If we don't have a selection we do not perform this
|
// If we don't have a selection we do not perform this
|
||||||
// action, allowing the keybind to fall through to the
|
// action, allowing the keybind to fall through to the
|
||||||
|
|
@ -5340,7 +5341,7 @@ fn writeScreenFile(
|
||||||
.history => history: {
|
.history => history: {
|
||||||
// We do not support this for alternate screens
|
// We do not support this for alternate screens
|
||||||
// because they don't have scrollback anyways.
|
// because they don't have scrollback anyways.
|
||||||
if (self.io.terminal.active_screen == .alternate) {
|
if (self.io.terminal.screens.active_key == .alternate) {
|
||||||
break :history null;
|
break :history null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5371,7 +5372,7 @@ fn writeScreenFile(
|
||||||
};
|
};
|
||||||
|
|
||||||
const ScreenFormatter = terminal.formatter.ScreenFormatter;
|
const ScreenFormatter = terminal.formatter.ScreenFormatter;
|
||||||
var formatter: ScreenFormatter = .init(&self.io.terminal.screen, .{
|
var formatter: ScreenFormatter = .init(self.io.terminal.screen, .{
|
||||||
.emit = switch (write_screen.emit) {
|
.emit = switch (write_screen.emit) {
|
||||||
.plain => .plain,
|
.plain => .plain,
|
||||||
.vt => .vt,
|
.vt => .vt,
|
||||||
|
|
@ -5384,7 +5385,7 @@ fn writeScreenFile(
|
||||||
.palette = &self.io.terminal.colors.palette.current,
|
.palette = &self.io.terminal.colors.palette.current,
|
||||||
});
|
});
|
||||||
formatter.content = .{ .selection = sel.ordered(
|
formatter.content = .{ .selection = sel.ordered(
|
||||||
&self.io.terminal.screen,
|
self.io.terminal.screen,
|
||||||
.forward,
|
.forward,
|
||||||
) };
|
) };
|
||||||
try formatter.format(buf_writer);
|
try formatter.format(buf_writer);
|
||||||
|
|
|
||||||
|
|
@ -1578,7 +1578,7 @@ pub const CAPI = struct {
|
||||||
defer surface.core_surface.renderer_state.mutex.unlock();
|
defer surface.core_surface.renderer_state.mutex.unlock();
|
||||||
|
|
||||||
const core_sel = sel.core(
|
const core_sel = sel.core(
|
||||||
&surface.core_surface.renderer_state.terminal.screen,
|
surface.core_surface.renderer_state.terminal.screen,
|
||||||
) orelse return false;
|
) orelse return false;
|
||||||
|
|
||||||
return readTextLocked(surface, core_sel, result);
|
return readTextLocked(surface, core_sel, result);
|
||||||
|
|
@ -2137,7 +2137,7 @@ pub const CAPI = struct {
|
||||||
|
|
||||||
// Get our word selection
|
// Get our word selection
|
||||||
const sel = sel: {
|
const sel = sel: {
|
||||||
const screen = &surface.renderer_state.terminal.screen;
|
const screen: *terminal.Screen = surface.renderer_state.terminal.screen;
|
||||||
const pos = try ptr.getCursorPos();
|
const pos = try ptr.getCursorPos();
|
||||||
const pt_viewport = surface.posToViewport(pos.x, pos.y);
|
const pt_viewport = surface.posToViewport(pos.x, pos.y);
|
||||||
const pin = screen.pages.pin(.{
|
const pin = screen.pages.pin(.{
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ fn renderScreenWindow(self: *Inspector) void {
|
||||||
)) return;
|
)) return;
|
||||||
|
|
||||||
const t = self.surface.renderer_state.terminal;
|
const t = self.surface.renderer_state.terminal;
|
||||||
const screen = &t.screen;
|
const screen: *terminal.Screen = t.screen;
|
||||||
|
|
||||||
{
|
{
|
||||||
_ = cimgui.c.igBeginTable(
|
_ = cimgui.c.igBeginTable(
|
||||||
|
|
@ -324,7 +324,7 @@ fn renderScreenWindow(self: *Inspector) void {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||||
cimgui.c.igText("%s", @tagName(t.active_screen).ptr);
|
cimgui.c.igText("%s", @tagName(t.screens.active_key).ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1066,7 +1066,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||||
bg: terminal.color.RGB,
|
bg: terminal.color.RGB,
|
||||||
fg: terminal.color.RGB,
|
fg: terminal.color.RGB,
|
||||||
screen: terminal.Screen,
|
screen: terminal.Screen,
|
||||||
screen_type: terminal.ScreenType,
|
screen_type: terminal.ScreenSet.Key,
|
||||||
mouse: renderer.State.Mouse,
|
mouse: renderer.State.Mouse,
|
||||||
preedit: ?renderer.State.Preedit,
|
preedit: ?renderer.State.Preedit,
|
||||||
cursor_color: ?terminal.color.RGB,
|
cursor_color: ?terminal.color.RGB,
|
||||||
|
|
@ -1207,7 +1207,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||||
.bg = bg,
|
.bg = bg,
|
||||||
.fg = fg,
|
.fg = fg,
|
||||||
.screen = screen_copy,
|
.screen = screen_copy,
|
||||||
.screen_type = state.terminal.active_screen,
|
.screen_type = state.terminal.screens.active_key,
|
||||||
.mouse = state.mouse,
|
.mouse = state.mouse,
|
||||||
.preedit = preedit,
|
.preedit = preedit,
|
||||||
.cursor_color = state.terminal.colors.cursor.get(),
|
.cursor_color = state.terminal.colors.cursor.get(),
|
||||||
|
|
@ -2317,7 +2317,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||||
self: *Self,
|
self: *Self,
|
||||||
wants_rebuild: bool,
|
wants_rebuild: bool,
|
||||||
screen: *terminal.Screen,
|
screen: *terminal.Screen,
|
||||||
screen_type: terminal.ScreenType,
|
screen_type: terminal.ScreenSet.Key,
|
||||||
mouse: renderer.State.Mouse,
|
mouse: renderer.State.Mouse,
|
||||||
preedit: ?renderer.State.Preedit,
|
preedit: ?renderer.State.Preedit,
|
||||||
cursor_style_: ?renderer.CursorStyle,
|
cursor_style_: ?renderer.CursorStyle,
|
||||||
|
|
|
||||||
|
|
@ -609,7 +609,7 @@ test "matchset osc8" {
|
||||||
// Initialize our terminal
|
// Initialize our terminal
|
||||||
var t = try Terminal.init(alloc, .{ .cols = 10, .rows = 10 });
|
var t = try Terminal.init(alloc, .{ .cols = 10, .rows = 10 });
|
||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
const s = &t.screen;
|
const s: *terminal.Screen = t.screen;
|
||||||
|
|
||||||
try t.printString("ABC");
|
try t.printString("ABC");
|
||||||
try t.screen.startHyperlink("http://example.com", null);
|
try t.screen.startHyperlink("http://example.com", null);
|
||||||
|
|
@ -624,7 +624,7 @@ test "matchset osc8" {
|
||||||
{
|
{
|
||||||
var match = try set.matchSet(
|
var match = try set.matchSet(
|
||||||
alloc,
|
alloc,
|
||||||
&t.screen,
|
t.screen,
|
||||||
.{ .x = 2, .y = 0 },
|
.{ .x = 2, .y = 0 },
|
||||||
inputpkg.ctrlOrSuper(.{}),
|
inputpkg.ctrlOrSuper(.{}),
|
||||||
);
|
);
|
||||||
|
|
@ -635,7 +635,7 @@ test "matchset osc8" {
|
||||||
// Match over link
|
// Match over link
|
||||||
var match = try set.matchSet(
|
var match = try set.matchSet(
|
||||||
alloc,
|
alloc,
|
||||||
&t.screen,
|
t.screen,
|
||||||
.{ .x = 3, .y = 0 },
|
.{ .x = 3, .y = 0 },
|
||||||
inputpkg.ctrlOrSuper(.{}),
|
inputpkg.ctrlOrSuper(.{}),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -178,8 +178,15 @@ pub const CharsetState = struct {
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
cols: size.CellCountInt,
|
cols: size.CellCountInt,
|
||||||
rows: size.CellCountInt,
|
rows: size.CellCountInt,
|
||||||
|
|
||||||
|
/// The maximum size of scrollback in bytes. Zero means unlimited. Any
|
||||||
|
/// other value will be clamped to support a minimum of the active area.
|
||||||
max_scrollback: usize = 0,
|
max_scrollback: usize = 0,
|
||||||
|
|
||||||
|
/// The total storage limit for Kitty images in bytes for this
|
||||||
|
/// screen. Kitty image storage is per-screen.
|
||||||
|
kitty_image_storage_limit: usize = 320 * 1000 * 1000, // 320MB
|
||||||
|
|
||||||
/// A simple, default terminal. If you rely on specific dimensions or
|
/// A simple, default terminal. If you rely on specific dimensions or
|
||||||
/// scrollback (or lack of) then do not use this directly. This is just
|
/// scrollback (or lack of) then do not use this directly. This is just
|
||||||
/// for callers that need some defaults.
|
/// for callers that need some defaults.
|
||||||
|
|
@ -215,7 +222,7 @@ pub fn init(
|
||||||
errdefer pages.untrackPin(page_pin);
|
errdefer pages.untrackPin(page_pin);
|
||||||
const page_rac = page_pin.rowAndCell();
|
const page_rac = page_pin.rowAndCell();
|
||||||
|
|
||||||
return .{
|
var result: Screen = .{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.pages = pages,
|
.pages = pages,
|
||||||
.no_scrollback = opts.max_scrollback == 0,
|
.no_scrollback = opts.max_scrollback == 0,
|
||||||
|
|
@ -227,6 +234,18 @@ pub fn init(
|
||||||
.page_cell = page_rac.cell,
|
.page_cell = page_rac.cell,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (comptime build_options.kitty_graphics) {
|
||||||
|
// This can't fail because the storage is always empty at this point
|
||||||
|
// and the only fail-able case is that we have to evict images.
|
||||||
|
result.kitty_images.setLimit(
|
||||||
|
alloc,
|
||||||
|
&result,
|
||||||
|
opts.kitty_image_storage_limit,
|
||||||
|
) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Screen) void {
|
pub fn deinit(self: *Screen) void {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
/// A ScreenSet holds multiple terminal screens. This is initially created
|
||||||
|
/// to handle simple primary vs alternate screens, but could be extended
|
||||||
|
/// in the future to handle N screens.
|
||||||
|
///
|
||||||
|
/// One of the goals of this is to allow lazy initialization of screens
|
||||||
|
/// as needed. The primary screen is always initialized, but the alternate
|
||||||
|
/// screen may not be until first used.
|
||||||
|
const ScreenSet = @This();
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const testing = std.testing;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Screen = @import("Screen.zig");
|
||||||
|
|
||||||
|
/// The possible keys for screens in the screen set.
|
||||||
|
pub const Key = enum(u1) {
|
||||||
|
primary,
|
||||||
|
alternate,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The key value of the currently active screen. Useful for simple
|
||||||
|
/// comparisons, e.g. "is this screen the primary screen".
|
||||||
|
active_key: Key,
|
||||||
|
|
||||||
|
/// The active screen pointer.
|
||||||
|
active: *Screen,
|
||||||
|
|
||||||
|
/// All screens that are initialized.
|
||||||
|
all: std.EnumMap(Key, *Screen),
|
||||||
|
|
||||||
|
pub fn init(
|
||||||
|
alloc: Allocator,
|
||||||
|
opts: Screen.Options,
|
||||||
|
) !ScreenSet {
|
||||||
|
// We need to initialize our initial primary screen
|
||||||
|
const screen = try alloc.create(Screen);
|
||||||
|
errdefer alloc.destroy(screen);
|
||||||
|
screen.* = try .init(alloc, opts);
|
||||||
|
return .{
|
||||||
|
.active_key = .primary,
|
||||||
|
.active = screen,
|
||||||
|
.all = .init(.{ .primary = screen }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *ScreenSet, alloc: Allocator) void {
|
||||||
|
// Destroy all initialized screens
|
||||||
|
var it = self.all.iterator();
|
||||||
|
while (it.next()) |entry| {
|
||||||
|
entry.value.*.deinit();
|
||||||
|
alloc.destroy(entry.value.*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the screen for the given key, if it is initialized.
|
||||||
|
pub fn get(self: *const ScreenSet, key: Key) ?*Screen {
|
||||||
|
return self.all.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the screen for the given key, initializing it if necessary.
|
||||||
|
pub fn getInit(
|
||||||
|
self: *ScreenSet,
|
||||||
|
alloc: Allocator,
|
||||||
|
key: Key,
|
||||||
|
opts: Screen.Options,
|
||||||
|
) !*Screen {
|
||||||
|
if (self.get(key)) |screen| return screen;
|
||||||
|
const screen = try alloc.create(Screen);
|
||||||
|
errdefer alloc.destroy(screen);
|
||||||
|
screen.* = try .init(alloc, opts);
|
||||||
|
self.all.put(key, screen);
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a key from the set. The primary screen cannot be removed (asserted).
|
||||||
|
pub fn remove(
|
||||||
|
self: *ScreenSet,
|
||||||
|
alloc: Allocator,
|
||||||
|
key: Key,
|
||||||
|
) void {
|
||||||
|
assert(key != .primary);
|
||||||
|
if (self.all.fetchRemove(key)) |screen| {
|
||||||
|
screen.deinit();
|
||||||
|
alloc.destroy(screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Switch the active screen to the given key. Requires that the
|
||||||
|
/// screen is initialized.
|
||||||
|
pub fn switchTo(self: *ScreenSet, key: Key) void {
|
||||||
|
self.active_key = key;
|
||||||
|
self.active = self.all.get(key).?;
|
||||||
|
}
|
||||||
|
|
||||||
|
test ScreenSet {
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var set: ScreenSet = try .init(alloc, .default);
|
||||||
|
defer set.deinit(alloc);
|
||||||
|
try testing.expectEqual(.primary, set.active_key);
|
||||||
|
|
||||||
|
// Initialize a secondary screen
|
||||||
|
_ = try set.getInit(alloc, .alternate, .default);
|
||||||
|
set.switchTo(.alternate);
|
||||||
|
try testing.expectEqual(.alternate, set.active_key);
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,7 @@ const size = @import("size.zig");
|
||||||
const pagepkg = @import("page.zig");
|
const pagepkg = @import("page.zig");
|
||||||
const style = @import("style.zig");
|
const style = @import("style.zig");
|
||||||
const Screen = @import("Screen.zig");
|
const Screen = @import("Screen.zig");
|
||||||
|
const ScreenSet = @import("ScreenSet.zig");
|
||||||
const Page = pagepkg.Page;
|
const Page = pagepkg.Page;
|
||||||
const Cell = pagepkg.Cell;
|
const Cell = pagepkg.Cell;
|
||||||
const Row = pagepkg.Row;
|
const Row = pagepkg.Row;
|
||||||
|
|
@ -38,18 +39,17 @@ const log = std.log.scoped(.terminal);
|
||||||
/// Default tabstop interval
|
/// Default tabstop interval
|
||||||
const TABSTOP_INTERVAL = 8;
|
const TABSTOP_INTERVAL = 8;
|
||||||
|
|
||||||
/// Screen type is an enum that tracks whether a screen is primary or alternate.
|
/// The currently active screen. To get the type of screen this is,
|
||||||
pub const ScreenType = enum(u1) {
|
/// inspect screens.active_key instead.
|
||||||
primary,
|
///
|
||||||
alternate,
|
/// Note: long term I'd like to get rid of this and force everyone
|
||||||
};
|
/// to go through screens instead but there's SO MUCH code that relies
|
||||||
|
/// on this property existing and it was really nasty to change all of
|
||||||
|
/// that today.
|
||||||
|
screen: *Screen,
|
||||||
|
|
||||||
/// Screen is the current screen state. The "active_screen" field says what
|
/// The set of screens behind this terminal (e.g. primary vs alternate).
|
||||||
/// the current screen is. The backup screen is the opposite of the active
|
screens: ScreenSet,
|
||||||
/// screen.
|
|
||||||
active_screen: ScreenType,
|
|
||||||
screen: Screen,
|
|
||||||
secondary_screen: Screen,
|
|
||||||
|
|
||||||
/// Whether we're currently writing to the status line (DECSASD and DECSSDT).
|
/// Whether we're currently writing to the status line (DECSASD and DECSSDT).
|
||||||
/// We don't support a status line currently so we just black hole this
|
/// We don't support a status line currently so we just black hole this
|
||||||
|
|
@ -221,12 +221,19 @@ pub fn init(
|
||||||
) !Terminal {
|
) !Terminal {
|
||||||
const cols = opts.cols;
|
const cols = opts.cols;
|
||||||
const rows = opts.rows;
|
const rows = opts.rows;
|
||||||
|
|
||||||
|
var screen_set: ScreenSet = try .init(alloc, .{
|
||||||
|
.cols = cols,
|
||||||
|
.rows = rows,
|
||||||
|
.max_scrollback = opts.max_scrollback,
|
||||||
|
});
|
||||||
|
errdefer screen_set.deinit(alloc);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.cols = cols,
|
.cols = cols,
|
||||||
.rows = rows,
|
.rows = rows,
|
||||||
.active_screen = .primary,
|
.screen = screen_set.active,
|
||||||
.screen = try .init(alloc, .{ .cols = cols, .rows = rows, .max_scrollback = opts.max_scrollback }),
|
.screens = screen_set,
|
||||||
.secondary_screen = try .init(alloc, .{ .cols = cols, .rows = rows, .max_scrollback = 0 }),
|
|
||||||
.tabstops = try .init(alloc, cols, TABSTOP_INTERVAL),
|
.tabstops = try .init(alloc, cols, TABSTOP_INTERVAL),
|
||||||
.scrolling_region = .{
|
.scrolling_region = .{
|
||||||
.top = 0,
|
.top = 0,
|
||||||
|
|
@ -245,8 +252,7 @@ pub fn init(
|
||||||
|
|
||||||
pub fn deinit(self: *Terminal, alloc: Allocator) void {
|
pub fn deinit(self: *Terminal, alloc: Allocator) void {
|
||||||
self.tabstops.deinit(alloc);
|
self.tabstops.deinit(alloc);
|
||||||
self.screen.deinit();
|
self.screens.deinit(alloc);
|
||||||
self.secondary_screen.deinit();
|
|
||||||
self.pwd.deinit(alloc);
|
self.pwd.deinit(alloc);
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
@ -266,7 +272,7 @@ pub fn vtHandler(self: *Terminal) ReadonlyHandler {
|
||||||
|
|
||||||
/// The general allocator we should use for this terminal.
|
/// The general allocator we should use for this terminal.
|
||||||
fn gpa(self: *Terminal) Allocator {
|
fn gpa(self: *Terminal) Allocator {
|
||||||
return self.screen.alloc;
|
return self.screens.active.alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print UTF-8 encoded string to the terminal.
|
/// Print UTF-8 encoded string to the terminal.
|
||||||
|
|
@ -1074,7 +1080,7 @@ pub fn markSemanticPrompt(self: *Terminal, p: SemanticPrompt) void {
|
||||||
/// If the shell integration doesn't exist, this will always return false.
|
/// If the shell integration doesn't exist, this will always return false.
|
||||||
pub fn cursorIsAtPrompt(self: *Terminal) bool {
|
pub fn cursorIsAtPrompt(self: *Terminal) bool {
|
||||||
// If we're on the secondary screen, we're never at a prompt.
|
// If we're on the secondary screen, we're never at a prompt.
|
||||||
if (self.active_screen == .alternate) return false;
|
if (self.screens.active_key == .alternate) return false;
|
||||||
|
|
||||||
// Reverse through the active
|
// Reverse through the active
|
||||||
const start_x, const start_y = .{ self.screen.cursor.x, self.screen.cursor.y };
|
const start_x, const start_y = .{ self.screen.cursor.x, self.screen.cursor.y };
|
||||||
|
|
@ -2202,7 +2208,7 @@ pub fn eraseDisplay(
|
||||||
// at a prompt scrolls the screen contents prior to clearing.
|
// at a prompt scrolls the screen contents prior to clearing.
|
||||||
// Most shells send `ESC [ H ESC [ 2 J` so we can't just check
|
// Most shells send `ESC [ H ESC [ 2 J` so we can't just check
|
||||||
// our current cursor position. See #905
|
// our current cursor position. See #905
|
||||||
if (self.active_screen == .primary) at_prompt: {
|
if (self.screens.active_key == .primary) at_prompt: {
|
||||||
// Go from the bottom of the active up and see if we're
|
// Go from the bottom of the active up and see if we're
|
||||||
// at a prompt.
|
// at a prompt.
|
||||||
const active_br = self.screen.pages.getBottomRight(
|
const active_br = self.screen.pages.getBottomRight(
|
||||||
|
|
@ -2531,25 +2537,22 @@ pub fn resize(
|
||||||
self.tabstops = try .init(alloc, cols, 8);
|
self.tabstops = try .init(alloc, cols, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're making the screen smaller, dealloc the unused items.
|
// Resize primary screen, which supports reflow
|
||||||
if (self.active_screen == .primary) {
|
const primary = self.screens.get(.primary).?;
|
||||||
if (self.flags.shell_redraws_prompt) {
|
if (self.screens.active_key == .primary and
|
||||||
self.screen.clearPrompt();
|
self.flags.shell_redraws_prompt)
|
||||||
}
|
{
|
||||||
|
primary.clearPrompt();
|
||||||
if (self.modes.get(.wraparound)) {
|
}
|
||||||
try self.screen.resize(cols, rows);
|
if (self.modes.get(.wraparound)) {
|
||||||
} else {
|
try primary.resize(cols, rows);
|
||||||
try self.screen.resizeWithoutReflow(cols, rows);
|
|
||||||
}
|
|
||||||
try self.secondary_screen.resizeWithoutReflow(cols, rows);
|
|
||||||
} else {
|
} else {
|
||||||
try self.screen.resizeWithoutReflow(cols, rows);
|
try primary.resizeWithoutReflow(cols, rows);
|
||||||
if (self.modes.get(.wraparound)) {
|
}
|
||||||
try self.secondary_screen.resize(cols, rows);
|
|
||||||
} else {
|
// Alternate screen, if it exists, doesn't reflow
|
||||||
try self.secondary_screen.resizeWithoutReflow(cols, rows);
|
if (self.screens.get(.alternate)) |alt| {
|
||||||
}
|
try alt.resizeWithoutReflow(cols, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whenever we resize we just mark it as a screen clear
|
// Whenever we resize we just mark it as a screen clear
|
||||||
|
|
@ -2581,14 +2584,6 @@ pub fn getPwd(self: *const Terminal) ?[]const u8 {
|
||||||
return self.pwd.items;
|
return self.pwd.items;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the screen pointer for the given type.
|
|
||||||
pub fn getScreen(self: *Terminal, t: ScreenType) *Screen {
|
|
||||||
return if (self.active_screen == t)
|
|
||||||
&self.screen
|
|
||||||
else
|
|
||||||
&self.secondary_screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Switch to the given screen type (alternate or primary).
|
/// Switch to the given screen type (alternate or primary).
|
||||||
///
|
///
|
||||||
/// This does NOT handle behaviors such as clearing the screen,
|
/// This does NOT handle behaviors such as clearing the screen,
|
||||||
|
|
@ -2604,40 +2599,60 @@ pub fn getScreen(self: *Terminal, t: ScreenType) *Screen {
|
||||||
/// more than two screens in the future if needed. There isn't
|
/// more than two screens in the future if needed. There isn't
|
||||||
/// currently a spec for this, but it is something I think might
|
/// currently a spec for this, but it is something I think might
|
||||||
/// be useful in the future.
|
/// be useful in the future.
|
||||||
pub fn switchScreen(self: *Terminal, t: ScreenType) ?*Screen {
|
pub fn switchScreen(self: *Terminal, key: ScreenSet.Key) !?*Screen {
|
||||||
// If we're already on the requested screen we do nothing.
|
// If we're already on the requested screen we do nothing.
|
||||||
if (self.active_screen == t) return null;
|
if (self.screens.active_key == key) return null;
|
||||||
|
const old = self.screens.active;
|
||||||
|
|
||||||
// We always end hyperlink state when switching screens.
|
// We always end hyperlink state when switching screens.
|
||||||
// We need to do this on the original screen.
|
// We need to do this on the original screen.
|
||||||
self.screen.endHyperlink();
|
old.endHyperlink();
|
||||||
|
|
||||||
// Switch the screens
|
// Switch the screens/
|
||||||
const old = self.screen;
|
const new = self.screens.get(key) orelse new: {
|
||||||
self.screen = self.secondary_screen;
|
const primary = self.screens.get(.primary).?;
|
||||||
self.secondary_screen = old;
|
break :new try self.screens.getInit(
|
||||||
self.active_screen = t;
|
old.alloc,
|
||||||
|
key,
|
||||||
|
.{
|
||||||
|
.cols = self.cols,
|
||||||
|
.rows = self.rows,
|
||||||
|
.max_scrollback = switch (key) {
|
||||||
|
.primary => primary.pages.explicit_max_size,
|
||||||
|
.alternate => 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Inherit our Kitty image storage limit from the primary
|
||||||
|
// screen if we have to initialize.
|
||||||
|
.kitty_image_storage_limit = primary.kitty_images.total_limit,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// The new screen should not have any hyperlinks set
|
// The new screen should not have any hyperlinks set
|
||||||
assert(self.screen.cursor.hyperlink_id == 0);
|
assert(new.cursor.hyperlink_id == 0);
|
||||||
|
|
||||||
// Bring our charset state with us
|
// Bring our charset state with us
|
||||||
self.screen.charset = old.charset;
|
new.charset = old.charset;
|
||||||
|
|
||||||
// Clear our selection
|
// Clear our selection
|
||||||
self.screen.clearSelection();
|
new.clearSelection();
|
||||||
|
|
||||||
if (comptime build_options.kitty_graphics) {
|
if (comptime build_options.kitty_graphics) {
|
||||||
// Mark kitty images as dirty so they redraw. Without this set
|
// Mark kitty images as dirty so they redraw. Without this set
|
||||||
// the images will remain where they were (the dirty bit on
|
// the images will remain where they were (the dirty bit on
|
||||||
// the screen only tracks the terminal grid, not the images).
|
// the screen only tracks the terminal grid, not the images).
|
||||||
self.screen.kitty_images.dirty = true;
|
new.kitty_images.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark our terminal as dirty to redraw the grid.
|
// Mark our terminal as dirty to redraw the grid.
|
||||||
self.flags.dirty.clear = true;
|
self.flags.dirty.clear = true;
|
||||||
|
|
||||||
return &self.secondary_screen;
|
// Finalize the switch
|
||||||
|
self.screens.switchTo(key);
|
||||||
|
self.screen = new;
|
||||||
|
|
||||||
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch screen via a mode switch (e.g. mode 47, 1047, 1049).
|
/// Switch screen via a mode switch (e.g. mode 47, 1047, 1049).
|
||||||
|
|
@ -2653,7 +2668,7 @@ pub fn switchScreenMode(
|
||||||
self: *Terminal,
|
self: *Terminal,
|
||||||
mode: SwitchScreenMode,
|
mode: SwitchScreenMode,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
) void {
|
) !void {
|
||||||
// The behavior in this function is completely based on reading
|
// The behavior in this function is completely based on reading
|
||||||
// the xterm source, specifically "charproc.c" for
|
// the xterm source, specifically "charproc.c" for
|
||||||
// `srm_ALTBUF`, `srm_OPT_ALTBUF`, and `srm_OPT_ALTBUF_CURSOR`.
|
// `srm_ALTBUF`, `srm_OPT_ALTBUF`, and `srm_OPT_ALTBUF_CURSOR`.
|
||||||
|
|
@ -2665,7 +2680,7 @@ pub fn switchScreenMode(
|
||||||
|
|
||||||
// If we're disabling 1047 and we're on alt screen then
|
// If we're disabling 1047 and we're on alt screen then
|
||||||
// we clear the screen.
|
// we clear the screen.
|
||||||
.@"1047" => if (!enabled and self.active_screen == .alternate) {
|
.@"1047" => if (!enabled and self.screens.active_key == .alternate) {
|
||||||
self.eraseDisplay(.complete, false);
|
self.eraseDisplay(.complete, false);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -2675,8 +2690,8 @@ pub fn switchScreenMode(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch screens first to whatever we're going to.
|
// Switch screens first to whatever we're going to.
|
||||||
const to: ScreenType = if (enabled) .alternate else .primary;
|
const to: ScreenSet.Key = if (enabled) .alternate else .primary;
|
||||||
const old_ = self.switchScreen(to);
|
const old_ = try self.switchScreen(to);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
// For these modes, we need to copy the cursor. We only copy
|
// For these modes, we need to copy the cursor. We only copy
|
||||||
|
|
@ -2697,7 +2712,7 @@ pub fn switchScreenMode(
|
||||||
// Mode 1049 restores cursor on the primary screen when
|
// Mode 1049 restores cursor on the primary screen when
|
||||||
// we disable it.
|
// we disable it.
|
||||||
.@"1049" => if (enabled) {
|
.@"1049" => if (enabled) {
|
||||||
assert(self.active_screen == .alternate);
|
assert(self.screens.active_key == .alternate);
|
||||||
self.eraseDisplay(.complete, false);
|
self.eraseDisplay(.complete, false);
|
||||||
|
|
||||||
// When we enter alt screen with 1049, we always copy the
|
// When we enter alt screen with 1049, we always copy the
|
||||||
|
|
@ -2714,7 +2729,7 @@ pub fn switchScreenMode(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(self.active_screen == .primary);
|
assert(self.screens.active_key == .primary);
|
||||||
self.restoreCursor() catch |err| {
|
self.restoreCursor() catch |err| {
|
||||||
log.warn(
|
log.warn(
|
||||||
"restore cursor on switch screen failed to={} err={}",
|
"restore cursor on switch screen failed to={} err={}",
|
||||||
|
|
@ -2765,17 +2780,16 @@ pub fn plainStringUnwrapped(self: *Terminal, alloc: Allocator) ![]const u8 {
|
||||||
/// this will reuse the existing memory. In the latter case, memory may
|
/// this will reuse the existing memory. In the latter case, memory may
|
||||||
/// be wasted (since its unused) but it isn't leaked.
|
/// be wasted (since its unused) but it isn't leaked.
|
||||||
pub fn fullReset(self: *Terminal) void {
|
pub fn fullReset(self: *Terminal) void {
|
||||||
// Reset our screens
|
|
||||||
self.screen.reset();
|
|
||||||
self.secondary_screen.reset();
|
|
||||||
|
|
||||||
// Ensure we're back on primary screen
|
// Ensure we're back on primary screen
|
||||||
if (self.active_screen != .primary) {
|
self.screens.switchTo(.primary);
|
||||||
const old = self.screen;
|
self.screens.remove(
|
||||||
self.screen = self.secondary_screen;
|
self.screens.active.alloc,
|
||||||
self.secondary_screen = old;
|
.alternate,
|
||||||
self.active_screen = .primary;
|
);
|
||||||
}
|
self.screen = self.screens.active;
|
||||||
|
|
||||||
|
// Reset our screens
|
||||||
|
self.screens.active.reset();
|
||||||
|
|
||||||
// Rest our basic state
|
// Rest our basic state
|
||||||
self.modes.reset();
|
self.modes.reset();
|
||||||
|
|
@ -10757,7 +10771,7 @@ test "Terminal: cursorIsAtPrompt alternate screen" {
|
||||||
try testing.expect(t.cursorIsAtPrompt());
|
try testing.expect(t.cursorIsAtPrompt());
|
||||||
|
|
||||||
// Secondary screen is never a prompt
|
// Secondary screen is never a prompt
|
||||||
t.switchScreenMode(.@"1049", true);
|
try t.switchScreenMode(.@"1049", true);
|
||||||
try testing.expect(!t.cursorIsAtPrompt());
|
try testing.expect(!t.cursorIsAtPrompt());
|
||||||
t.markSemanticPrompt(.prompt);
|
t.markSemanticPrompt(.prompt);
|
||||||
try testing.expect(!t.cursorIsAtPrompt());
|
try testing.expect(!t.cursorIsAtPrompt());
|
||||||
|
|
@ -10841,7 +10855,7 @@ test "Terminal: fullReset clears alt screen kitty keyboard state" {
|
||||||
var t = try init(testing.allocator, .{ .cols = 10, .rows = 10 });
|
var t = try init(testing.allocator, .{ .cols = 10, .rows = 10 });
|
||||||
defer t.deinit(testing.allocator);
|
defer t.deinit(testing.allocator);
|
||||||
|
|
||||||
t.switchScreenMode(.@"1049", true);
|
try t.switchScreenMode(.@"1049", true);
|
||||||
t.screen.kitty_keyboard.push(.{
|
t.screen.kitty_keyboard.push(.{
|
||||||
.disambiguate = true,
|
.disambiguate = true,
|
||||||
.report_events = false,
|
.report_events = false,
|
||||||
|
|
@ -10849,10 +10863,10 @@ test "Terminal: fullReset clears alt screen kitty keyboard state" {
|
||||||
.report_all = true,
|
.report_all = true,
|
||||||
.report_associated = true,
|
.report_associated = true,
|
||||||
});
|
});
|
||||||
t.switchScreenMode(.@"1049", false);
|
try t.switchScreenMode(.@"1049", false);
|
||||||
|
|
||||||
t.fullReset();
|
t.fullReset();
|
||||||
try testing.expectEqual(0, t.secondary_screen.kitty_keyboard.current().int());
|
try testing.expect(t.screens.get(.alternate) == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Terminal: fullReset default modes" {
|
test "Terminal: fullReset default modes" {
|
||||||
|
|
@ -11164,8 +11178,8 @@ test "Terminal: mode 47 alt screen plain" {
|
||||||
try t.printString("1A");
|
try t.printString("1A");
|
||||||
|
|
||||||
// Go to alt screen with mode 47
|
// Go to alt screen with mode 47
|
||||||
t.switchScreenMode(.@"47", true);
|
try t.switchScreenMode(.@"47", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Screen should be empty
|
// Screen should be empty
|
||||||
{
|
{
|
||||||
|
|
@ -11184,8 +11198,8 @@ test "Terminal: mode 47 alt screen plain" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to primary
|
// Go back to primary
|
||||||
t.switchScreenMode(.@"47", false);
|
try t.switchScreenMode(.@"47", false);
|
||||||
try testing.expectEqual(ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
// Primary screen should still have the original content
|
// Primary screen should still have the original content
|
||||||
{
|
{
|
||||||
|
|
@ -11195,8 +11209,8 @@ test "Terminal: mode 47 alt screen plain" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to alt screen with mode 47
|
// Go back to alt screen with mode 47
|
||||||
t.switchScreenMode(.@"47", true);
|
try t.switchScreenMode(.@"47", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Screen should retain content
|
// Screen should retain content
|
||||||
{
|
{
|
||||||
|
|
@ -11215,8 +11229,8 @@ test "Terminal: mode 47 copies cursor both directions" {
|
||||||
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0xFF, .g = 0, .b = 0x7F } });
|
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0xFF, .g = 0, .b = 0x7F } });
|
||||||
|
|
||||||
// Go to alt screen with mode 47
|
// Go to alt screen with mode 47
|
||||||
t.switchScreenMode(.@"47", true);
|
try t.switchScreenMode(.@"47", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Verify that our style is set
|
// Verify that our style is set
|
||||||
{
|
{
|
||||||
|
|
@ -11230,8 +11244,8 @@ test "Terminal: mode 47 copies cursor both directions" {
|
||||||
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0, .g = 0xFF, .b = 0 } });
|
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0, .g = 0xFF, .b = 0 } });
|
||||||
|
|
||||||
// Go back to primary
|
// Go back to primary
|
||||||
t.switchScreenMode(.@"47", false);
|
try t.switchScreenMode(.@"47", false);
|
||||||
try testing.expectEqual(ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
// Verify that our style is still set
|
// Verify that our style is still set
|
||||||
{
|
{
|
||||||
|
|
@ -11251,8 +11265,8 @@ test "Terminal: mode 1047 alt screen plain" {
|
||||||
try t.printString("1A");
|
try t.printString("1A");
|
||||||
|
|
||||||
// Go to alt screen with mode 47
|
// Go to alt screen with mode 47
|
||||||
t.switchScreenMode(.@"1047", true);
|
try t.switchScreenMode(.@"1047", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Screen should be empty
|
// Screen should be empty
|
||||||
{
|
{
|
||||||
|
|
@ -11271,8 +11285,8 @@ test "Terminal: mode 1047 alt screen plain" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to primary
|
// Go back to primary
|
||||||
t.switchScreenMode(.@"1047", false);
|
try t.switchScreenMode(.@"1047", false);
|
||||||
try testing.expectEqual(ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
// Primary screen should still have the original content
|
// Primary screen should still have the original content
|
||||||
{
|
{
|
||||||
|
|
@ -11282,8 +11296,8 @@ test "Terminal: mode 1047 alt screen plain" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to alt screen with mode 1047
|
// Go back to alt screen with mode 1047
|
||||||
t.switchScreenMode(.@"1047", true);
|
try t.switchScreenMode(.@"1047", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Screen should be empty
|
// Screen should be empty
|
||||||
{
|
{
|
||||||
|
|
@ -11302,8 +11316,8 @@ test "Terminal: mode 1047 copies cursor both directions" {
|
||||||
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0xFF, .g = 0, .b = 0x7F } });
|
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0xFF, .g = 0, .b = 0x7F } });
|
||||||
|
|
||||||
// Go to alt screen with mode 47
|
// Go to alt screen with mode 47
|
||||||
t.switchScreenMode(.@"1047", true);
|
try t.switchScreenMode(.@"1047", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Verify that our style is set
|
// Verify that our style is set
|
||||||
{
|
{
|
||||||
|
|
@ -11317,8 +11331,8 @@ test "Terminal: mode 1047 copies cursor both directions" {
|
||||||
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0, .g = 0xFF, .b = 0 } });
|
try t.setAttribute(.{ .direct_color_fg = .{ .r = 0, .g = 0xFF, .b = 0 } });
|
||||||
|
|
||||||
// Go back to primary
|
// Go back to primary
|
||||||
t.switchScreenMode(.@"1047", false);
|
try t.switchScreenMode(.@"1047", false);
|
||||||
try testing.expectEqual(ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
// Verify that our style is still set
|
// Verify that our style is still set
|
||||||
{
|
{
|
||||||
|
|
@ -11338,8 +11352,8 @@ test "Terminal: mode 1049 alt screen plain" {
|
||||||
try t.printString("1A");
|
try t.printString("1A");
|
||||||
|
|
||||||
// Go to alt screen with mode 47
|
// Go to alt screen with mode 47
|
||||||
t.switchScreenMode(.@"1049", true);
|
try t.switchScreenMode(.@"1049", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Screen should be empty
|
// Screen should be empty
|
||||||
{
|
{
|
||||||
|
|
@ -11358,8 +11372,8 @@ test "Terminal: mode 1049 alt screen plain" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to primary
|
// Go back to primary
|
||||||
t.switchScreenMode(.@"1049", false);
|
try t.switchScreenMode(.@"1049", false);
|
||||||
try testing.expectEqual(ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
// Primary screen should still have the original content
|
// Primary screen should still have the original content
|
||||||
{
|
{
|
||||||
|
|
@ -11377,8 +11391,8 @@ test "Terminal: mode 1049 alt screen plain" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go back to alt screen with mode 1049
|
// Go back to alt screen with mode 1049
|
||||||
t.switchScreenMode(.@"1049", true);
|
try t.switchScreenMode(.@"1049", true);
|
||||||
try testing.expectEqual(ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Screen should be empty
|
// Screen should be empty
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ pub const TerminalFormatter = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var screen_formatter: ScreenFormatter = .init(&self.terminal.screen, self.opts);
|
var screen_formatter: ScreenFormatter = .init(self.terminal.screen, self.opts);
|
||||||
screen_formatter.content = self.content;
|
screen_formatter.content = self.content;
|
||||||
screen_formatter.extra = self.extra.screen;
|
screen_formatter.extra = self.extra.screen;
|
||||||
screen_formatter.pin_map = self.pin_map;
|
screen_formatter.pin_map = self.pin_map;
|
||||||
|
|
@ -4231,7 +4231,7 @@ test "Screen plain single line" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .plain);
|
var formatter: ScreenFormatter = .init(t.screen, .plain);
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
try formatter.format(&builder.writer);
|
try formatter.format(&builder.writer);
|
||||||
|
|
@ -4268,7 +4268,7 @@ test "Screen plain multiline" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .plain);
|
var formatter: ScreenFormatter = .init(t.screen, .plain);
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
try formatter.format(&builder.writer);
|
try formatter.format(&builder.writer);
|
||||||
|
|
@ -4316,7 +4316,7 @@ test "Screen plain with selection" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .plain);
|
var formatter: ScreenFormatter = .init(t.screen, .plain);
|
||||||
formatter.content = .{ .selection = .init(
|
formatter.content = .{ .selection = .init(
|
||||||
t.screen.pages.pin(.{ .active = .{ .x = 0, .y = 1 } }).?,
|
t.screen.pages.pin(.{ .active = .{ .x = 0, .y = 1 } }).?,
|
||||||
t.screen.pages.pin(.{ .active = .{ .x = 4, .y = 1 } }).?,
|
t.screen.pages.pin(.{ .active = .{ .x = 4, .y = 1 } }).?,
|
||||||
|
|
@ -4361,7 +4361,7 @@ test "Screen vt with cursor position" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .vt);
|
var formatter: ScreenFormatter = .init(t.screen, .vt);
|
||||||
formatter.extra.cursor = true;
|
formatter.extra.cursor = true;
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
|
|
@ -4420,7 +4420,7 @@ test "Screen vt with style" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .vt);
|
var formatter: ScreenFormatter = .init(t.screen, .vt);
|
||||||
formatter.extra.style = true;
|
formatter.extra.style = true;
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
|
|
@ -4472,7 +4472,7 @@ test "Screen vt with hyperlink" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .vt);
|
var formatter: ScreenFormatter = .init(t.screen, .vt);
|
||||||
formatter.extra.hyperlink = true;
|
formatter.extra.hyperlink = true;
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
|
|
@ -4532,7 +4532,7 @@ test "Screen vt with protection" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .vt);
|
var formatter: ScreenFormatter = .init(t.screen, .vt);
|
||||||
formatter.extra.protection = true;
|
formatter.extra.protection = true;
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
|
|
@ -4584,7 +4584,7 @@ test "Screen vt with kitty keyboard" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .vt);
|
var formatter: ScreenFormatter = .init(t.screen, .vt);
|
||||||
formatter.extra.kitty_keyboard = true;
|
formatter.extra.kitty_keyboard = true;
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
|
|
@ -4638,7 +4638,7 @@ test "Screen vt with charsets" {
|
||||||
var pin_map: std.ArrayList(Pin) = .empty;
|
var pin_map: std.ArrayList(Pin) = .empty;
|
||||||
defer pin_map.deinit(alloc);
|
defer pin_map.deinit(alloc);
|
||||||
|
|
||||||
var formatter: ScreenFormatter = .init(&t.screen, .vt);
|
var formatter: ScreenFormatter = .init(t.screen, .vt);
|
||||||
formatter.extra.charsets = true;
|
formatter.extra.charsets = true;
|
||||||
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
formatter.pin_map = .{ .alloc = alloc, .map = &pin_map };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ fn display(
|
||||||
result.placement_id,
|
result.placement_id,
|
||||||
p,
|
p,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
p.deinit(&terminal.screen);
|
p.deinit(terminal.screen);
|
||||||
encodeError(&result, err);
|
encodeError(&result, err);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ pub const ImageStorage = struct {
|
||||||
|
|
||||||
// Deinit the placement and remove it
|
// Deinit the placement and remove it
|
||||||
const image_id = entry.key_ptr.image_id;
|
const image_id = entry.key_ptr.image_id;
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
if (delete_images) self.deleteIfUnused(alloc, image_id);
|
if (delete_images) self.deleteIfUnused(alloc, image_id);
|
||||||
}
|
}
|
||||||
|
|
@ -247,7 +247,7 @@ pub const ImageStorage = struct {
|
||||||
|
|
||||||
.id => |v| self.deleteById(
|
.id => |v| self.deleteById(
|
||||||
alloc,
|
alloc,
|
||||||
&t.screen,
|
t.screen,
|
||||||
v.image_id,
|
v.image_id,
|
||||||
v.placement_id,
|
v.placement_id,
|
||||||
v.delete,
|
v.delete,
|
||||||
|
|
@ -257,7 +257,7 @@ pub const ImageStorage = struct {
|
||||||
const img = self.imageByNumber(v.image_number) orelse break :newest;
|
const img = self.imageByNumber(v.image_number) orelse break :newest;
|
||||||
self.deleteById(
|
self.deleteById(
|
||||||
alloc,
|
alloc,
|
||||||
&t.screen,
|
t.screen,
|
||||||
img.id,
|
img.id,
|
||||||
v.placement_id,
|
v.placement_id,
|
||||||
v.delete,
|
v.delete,
|
||||||
|
|
@ -332,7 +332,7 @@ pub const ImageStorage = struct {
|
||||||
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
const img = self.imageById(entry.key_ptr.image_id) orelse continue;
|
||||||
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
||||||
if (rect.top_left.x <= x and rect.bottom_right.x >= x) {
|
if (rect.top_left.x <= x and rect.bottom_right.x >= x) {
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
if (v.delete) self.deleteIfUnused(alloc, img.id);
|
if (v.delete) self.deleteIfUnused(alloc, img.id);
|
||||||
}
|
}
|
||||||
|
|
@ -364,7 +364,7 @@ pub const ImageStorage = struct {
|
||||||
var target_pin_copy = target_pin;
|
var target_pin_copy = target_pin;
|
||||||
target_pin_copy.x = rect.top_left.x;
|
target_pin_copy.x = rect.top_left.x;
|
||||||
if (target_pin_copy.isBetween(rect.top_left, rect.bottom_right)) {
|
if (target_pin_copy.isBetween(rect.top_left, rect.bottom_right)) {
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
if (v.delete) self.deleteIfUnused(alloc, img.id);
|
if (v.delete) self.deleteIfUnused(alloc, img.id);
|
||||||
}
|
}
|
||||||
|
|
@ -387,7 +387,7 @@ pub const ImageStorage = struct {
|
||||||
|
|
||||||
if (entry.value_ptr.z == v.z) {
|
if (entry.value_ptr.z == v.z) {
|
||||||
const image_id = entry.key_ptr.image_id;
|
const image_id = entry.key_ptr.image_id;
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
if (v.delete) self.deleteIfUnused(alloc, image_id);
|
if (v.delete) self.deleteIfUnused(alloc, image_id);
|
||||||
}
|
}
|
||||||
|
|
@ -411,7 +411,7 @@ pub const ImageStorage = struct {
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
if (entry.key_ptr.image_id >= v.first or entry.key_ptr.image_id <= v.last) {
|
if (entry.key_ptr.image_id >= v.first or entry.key_ptr.image_id <= v.last) {
|
||||||
const image_id = entry.key_ptr.image_id;
|
const image_id = entry.key_ptr.image_id;
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
if (v.delete) self.deleteIfUnused(alloc, image_id);
|
if (v.delete) self.deleteIfUnused(alloc, image_id);
|
||||||
}
|
}
|
||||||
|
|
@ -498,7 +498,7 @@ pub const ImageStorage = struct {
|
||||||
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
const rect = entry.value_ptr.rect(img, t) orelse continue;
|
||||||
if (target_pin.isBetween(rect.top_left, rect.bottom_right)) {
|
if (target_pin.isBetween(rect.top_left, rect.bottom_right)) {
|
||||||
if (filter) |f| if (!f(filter_ctx, entry.value_ptr.*)) continue;
|
if (filter) |f| if (!f(filter_ctx, entry.value_ptr.*)) continue;
|
||||||
entry.value_ptr.deinit(&t.screen);
|
entry.value_ptr.deinit(t.screen);
|
||||||
self.placements.removeByPtr(entry.key_ptr);
|
self.placements.removeByPtr(entry.key_ptr);
|
||||||
if (delete_unused) self.deleteIfUnused(alloc, img.id);
|
if (delete_unused) self.deleteIfUnused(alloc, img.id);
|
||||||
}
|
}
|
||||||
|
|
@ -825,7 +825,7 @@ test "storage: add placement with zero placement id" {
|
||||||
t.height_px = 100;
|
t.height_px = 100;
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
||||||
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
||||||
try s.addPlacement(alloc, 1, 0, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
|
try s.addPlacement(alloc, 1, 0, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 25, .y = 25 }) } });
|
||||||
|
|
@ -853,7 +853,7 @@ test "storage: delete all placements and images" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -876,7 +876,7 @@ test "storage: delete all placements and images preserves limit" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
s.total_limit = 5000;
|
s.total_limit = 5000;
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
|
|
@ -901,7 +901,7 @@ test "storage: delete all placements" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -924,7 +924,7 @@ test "storage: delete all placements by image id" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -947,7 +947,7 @@ test "storage: delete all placements by image id and unused images" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -970,7 +970,7 @@ test "storage: delete placement by specific id" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -1000,7 +1000,7 @@ test "storage: delete intersecting cursor" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
||||||
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
||||||
|
|
@ -1032,7 +1032,7 @@ test "storage: delete intersecting cursor plus unused" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
||||||
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
||||||
|
|
@ -1064,7 +1064,7 @@ test "storage: delete intersecting cursor hits multiple" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
||||||
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
||||||
|
|
@ -1090,7 +1090,7 @@ test "storage: delete by column" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
||||||
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
||||||
|
|
@ -1122,7 +1122,7 @@ test "storage: delete by column 1x1" {
|
||||||
t.height_px = 100;
|
t.height_px = 100;
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 });
|
try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
||||||
try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 1, .y = 0 }) } });
|
||||||
|
|
@ -1156,7 +1156,7 @@ test "storage: delete by row" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
try s.addImage(alloc, .{ .id = 1, .width = 50, .height = 50 });
|
||||||
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
try s.addImage(alloc, .{ .id = 2, .width = 25, .height = 25 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .x = 0, .y = 0 }) } });
|
||||||
|
|
@ -1188,7 +1188,7 @@ test "storage: delete by row 1x1" {
|
||||||
t.height_px = 100;
|
t.height_px = 100;
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 });
|
try s.addImage(alloc, .{ .id = 1, .width = 1, .height = 1 });
|
||||||
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 0 }) } });
|
try s.addPlacement(alloc, 1, 1, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 0 }) } });
|
||||||
try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 1 }) } });
|
try s.addPlacement(alloc, 1, 2, .{ .location = .{ .pin = try trackPin(&t, .{ .y = 1 }) } });
|
||||||
|
|
@ -1220,7 +1220,7 @@ test "storage: delete images by range 1" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -1245,7 +1245,7 @@ test "storage: delete images by range 2" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -1270,7 +1270,7 @@ test "storage: delete images by range 3" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
@ -1295,7 +1295,7 @@ test "storage: delete images by range 4" {
|
||||||
const tracked = t.screen.pages.countTrackedPins();
|
const tracked = t.screen.pages.countTrackedPins();
|
||||||
|
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
try s.addImage(alloc, .{ .id = 1 });
|
try s.addImage(alloc, .{ .id = 1 });
|
||||||
try s.addImage(alloc, .{ .id = 2 });
|
try s.addImage(alloc, .{ .id = 2 });
|
||||||
try s.addImage(alloc, .{ .id = 3 });
|
try s.addImage(alloc, .{ .id = 3 });
|
||||||
|
|
|
||||||
|
|
@ -1180,7 +1180,7 @@ test "unicode render placement: dog 4x2" {
|
||||||
var t = try terminal.Terminal.init(alloc, .{ .cols = 100, .rows = 100 });
|
var t = try terminal.Terminal.init(alloc, .{ .cols = 100, .rows = 100 });
|
||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
|
|
||||||
const image: Image = .{ .id = 1, .width = 500, .height = 306 };
|
const image: Image = .{ .id = 1, .width = 500, .height = 306 };
|
||||||
try s.addImage(alloc, image);
|
try s.addImage(alloc, image);
|
||||||
|
|
@ -1247,7 +1247,7 @@ test "unicode render placement: dog 2x2 with blank cells" {
|
||||||
var t = try terminal.Terminal.init(alloc, .{ .cols = 100, .rows = 100 });
|
var t = try terminal.Terminal.init(alloc, .{ .cols = 100, .rows = 100 });
|
||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
|
|
||||||
const image: Image = .{ .id = 1, .width = 500, .height = 306 };
|
const image: Image = .{ .id = 1, .width = 500, .height = 306 };
|
||||||
try s.addImage(alloc, image);
|
try s.addImage(alloc, image);
|
||||||
|
|
@ -1313,7 +1313,7 @@ test "unicode render placement: dog 1x1" {
|
||||||
var t = try terminal.Terminal.init(alloc, .{ .cols = 100, .rows = 100 });
|
var t = try terminal.Terminal.init(alloc, .{ .cols = 100, .rows = 100 });
|
||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
var s: ImageStorage = .{};
|
var s: ImageStorage = .{};
|
||||||
defer s.deinit(alloc, &t.screen);
|
defer s.deinit(alloc, t.screen);
|
||||||
|
|
||||||
const image: Image = .{ .id = 1, .width = 500, .height = 306 };
|
const image: Image = .{ .id = 1, .width = 500, .height = 306 };
|
||||||
try s.addImage(alloc, image);
|
try s.addImage(alloc, image);
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ pub const Point = point.Point;
|
||||||
pub const ReadonlyHandler = stream_readonly.Handler;
|
pub const ReadonlyHandler = stream_readonly.Handler;
|
||||||
pub const ReadonlyStream = stream_readonly.Stream;
|
pub const ReadonlyStream = stream_readonly.Stream;
|
||||||
pub const Screen = @import("Screen.zig");
|
pub const Screen = @import("Screen.zig");
|
||||||
pub const ScreenType = Terminal.ScreenType;
|
pub const ScreenSet = @import("ScreenSet.zig");
|
||||||
pub const Scrollbar = PageList.Scrollbar;
|
pub const Scrollbar = PageList.Scrollbar;
|
||||||
pub const Selection = @import("Selection.zig");
|
pub const Selection = @import("Selection.zig");
|
||||||
pub const SizeReportStyle = csi.SizeReportStyle;
|
pub const SizeReportStyle = csi.SizeReportStyle;
|
||||||
|
|
|
||||||
|
|
@ -391,7 +391,7 @@ test "simple search" {
|
||||||
defer s.deinit();
|
defer s.deinit();
|
||||||
try s.nextSlice("Fizz\r\nBuzz\r\nFizz\r\nBang");
|
try s.nextSlice("Fizz\r\nBuzz\r\nFizz\r\nBang");
|
||||||
|
|
||||||
var search: ScreenSearch = try .init(alloc, &t.screen, "Fizz");
|
var search: ScreenSearch = try .init(alloc, t.screen, "Fizz");
|
||||||
defer search.deinit();
|
defer search.deinit();
|
||||||
try search.searchAll();
|
try search.searchAll();
|
||||||
try testing.expectEqual(2, search.active_results.items.len);
|
try testing.expectEqual(2, search.active_results.items.len);
|
||||||
|
|
@ -444,7 +444,7 @@ test "simple search with history" {
|
||||||
for (0..list.rows) |_| try s.nextSlice("\r\n");
|
for (0..list.rows) |_| try s.nextSlice("\r\n");
|
||||||
try s.nextSlice("hello.");
|
try s.nextSlice("hello.");
|
||||||
|
|
||||||
var search: ScreenSearch = try .init(alloc, &t.screen, "Fizz");
|
var search: ScreenSearch = try .init(alloc, t.screen, "Fizz");
|
||||||
defer search.deinit();
|
defer search.deinit();
|
||||||
try search.searchAll();
|
try search.searchAll();
|
||||||
try testing.expectEqual(0, search.active_results.items.len);
|
try testing.expectEqual(0, search.active_results.items.len);
|
||||||
|
|
@ -482,7 +482,7 @@ test "reload active with history change" {
|
||||||
try s.nextSlice("Fizz\r\n");
|
try s.nextSlice("Fizz\r\n");
|
||||||
|
|
||||||
// Start up our search which will populate our initial active area.
|
// Start up our search which will populate our initial active area.
|
||||||
var search: ScreenSearch = try .init(alloc, &t.screen, "Fizz");
|
var search: ScreenSearch = try .init(alloc, t.screen, "Fizz");
|
||||||
defer search.deinit();
|
defer search.deinit();
|
||||||
try search.searchAll();
|
try search.searchAll();
|
||||||
{
|
{
|
||||||
|
|
@ -562,7 +562,7 @@ test "active change contents" {
|
||||||
defer s.deinit();
|
defer s.deinit();
|
||||||
try s.nextSlice("Fuzz\r\nBuzz\r\nFizz\r\nBang");
|
try s.nextSlice("Fuzz\r\nBuzz\r\nFizz\r\nBang");
|
||||||
|
|
||||||
var search: ScreenSearch = try .init(alloc, &t.screen, "Fizz");
|
var search: ScreenSearch = try .init(alloc, t.screen, "Fizz");
|
||||||
defer search.deinit();
|
defer search.deinit();
|
||||||
try search.searchAll();
|
try search.searchAll();
|
||||||
try testing.expectEqual(1, search.active_results.items.len);
|
try testing.expectEqual(1, search.active_results.items.len);
|
||||||
|
|
|
||||||
|
|
@ -233,9 +233,9 @@ pub const Handler = struct {
|
||||||
self.terminal.scrolling_region.right = self.terminal.cols - 1;
|
self.terminal.scrolling_region.right = self.terminal.cols - 1;
|
||||||
},
|
},
|
||||||
|
|
||||||
.alt_screen_legacy => self.terminal.switchScreenMode(.@"47", enabled),
|
.alt_screen_legacy => try self.terminal.switchScreenMode(.@"47", enabled),
|
||||||
.alt_screen => self.terminal.switchScreenMode(.@"1047", enabled),
|
.alt_screen => try self.terminal.switchScreenMode(.@"1047", enabled),
|
||||||
.alt_screen_save_cursor_clear_enter => self.terminal.switchScreenMode(.@"1049", enabled),
|
.alt_screen_save_cursor_clear_enter => try self.terminal.switchScreenMode(.@"1049", enabled),
|
||||||
|
|
||||||
.save_cursor => if (enabled) {
|
.save_cursor => if (enabled) {
|
||||||
self.terminal.saveCursor();
|
self.terminal.saveCursor();
|
||||||
|
|
@ -527,18 +527,18 @@ test "alt screen" {
|
||||||
|
|
||||||
// Write to primary screen
|
// Write to primary screen
|
||||||
try s.nextSlice("Primary");
|
try s.nextSlice("Primary");
|
||||||
try testing.expectEqual(Terminal.ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
// Switch to alt screen
|
// Switch to alt screen
|
||||||
try s.nextSlice("\x1B[?1049h");
|
try s.nextSlice("\x1B[?1049h");
|
||||||
try testing.expectEqual(Terminal.ScreenType.alternate, t.active_screen);
|
try testing.expectEqual(.alternate, t.screens.active_key);
|
||||||
|
|
||||||
// Write to alt screen
|
// Write to alt screen
|
||||||
try s.nextSlice("Alt");
|
try s.nextSlice("Alt");
|
||||||
|
|
||||||
// Switch back to primary
|
// Switch back to primary
|
||||||
try s.nextSlice("\x1B[?1049l");
|
try s.nextSlice("\x1B[?1049l");
|
||||||
try testing.expectEqual(Terminal.ScreenType.primary, t.active_screen);
|
try testing.expectEqual(.primary, t.screens.active_key);
|
||||||
|
|
||||||
const str = try t.plainString(testing.allocator);
|
const str = try t.plainString(testing.allocator);
|
||||||
defer testing.allocator.free(str);
|
defer testing.allocator.free(str);
|
||||||
|
|
|
||||||
|
|
@ -246,16 +246,15 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
||||||
errdefer term.deinit(alloc);
|
errdefer term.deinit(alloc);
|
||||||
|
|
||||||
// Set the image size limits
|
// Set the image size limits
|
||||||
try term.screen.kitty_images.setLimit(
|
var it = term.screens.all.iterator();
|
||||||
alloc,
|
while (it.next()) |entry| {
|
||||||
&term.screen,
|
const screen: *terminalpkg.Screen = entry.value.*;
|
||||||
opts.config.image_storage_limit,
|
try screen.kitty_images.setLimit(
|
||||||
);
|
alloc,
|
||||||
try term.secondary_screen.kitty_images.setLimit(
|
screen,
|
||||||
alloc,
|
opts.config.image_storage_limit,
|
||||||
&term.secondary_screen,
|
);
|
||||||
opts.config.image_storage_limit,
|
}
|
||||||
);
|
|
||||||
|
|
||||||
// Set our default cursor style
|
// Set our default cursor style
|
||||||
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
||||||
|
|
@ -451,16 +450,15 @@ pub fn changeConfig(self: *Termio, td: *ThreadData, config: *DerivedConfig) !voi
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the image size limits
|
// Set the image size limits
|
||||||
try self.terminal.screen.kitty_images.setLimit(
|
var it = self.terminal.screens.all.iterator();
|
||||||
self.alloc,
|
while (it.next()) |entry| {
|
||||||
&self.terminal.screen,
|
const screen: *terminalpkg.Screen = entry.value.*;
|
||||||
config.image_storage_limit,
|
try screen.kitty_images.setLimit(
|
||||||
);
|
self.alloc,
|
||||||
try self.terminal.secondary_screen.kitty_images.setLimit(
|
screen,
|
||||||
self.alloc,
|
config.image_storage_limit,
|
||||||
&self.terminal.secondary_screen,
|
);
|
||||||
config.image_storage_limit,
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize the terminal.
|
/// Resize the terminal.
|
||||||
|
|
@ -578,7 +576,7 @@ pub fn clearScreen(self: *Termio, td: *ThreadData, history: bool) !void {
|
||||||
// emulator-level screen clear, this messes up the running programs
|
// emulator-level screen clear, this messes up the running programs
|
||||||
// knowledge of where the cursor is and causes rendering issues. So,
|
// knowledge of where the cursor is and causes rendering issues. So,
|
||||||
// for alt screen, we do nothing.
|
// for alt screen, we do nothing.
|
||||||
if (self.terminal.active_screen == .alternate) return;
|
if (self.terminal.screens.active_key == .alternate) return;
|
||||||
|
|
||||||
// Clear our selection
|
// Clear our selection
|
||||||
self.terminal.screen.clearSelection();
|
self.terminal.screen.clearSelection();
|
||||||
|
|
|
||||||
|
|
@ -583,15 +583,15 @@ pub const StreamHandler = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
.alt_screen_legacy => {
|
.alt_screen_legacy => {
|
||||||
self.terminal.switchScreenMode(.@"47", enabled);
|
try self.terminal.switchScreenMode(.@"47", enabled);
|
||||||
},
|
},
|
||||||
|
|
||||||
.alt_screen => {
|
.alt_screen => {
|
||||||
self.terminal.switchScreenMode(.@"1047", enabled);
|
try self.terminal.switchScreenMode(.@"1047", enabled);
|
||||||
},
|
},
|
||||||
|
|
||||||
.alt_screen_save_cursor_clear_enter => {
|
.alt_screen_save_cursor_clear_enter => {
|
||||||
self.terminal.switchScreenMode(.@"1049", enabled);
|
try self.terminal.switchScreenMode(.@"1049", enabled);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Mode 1048 is xterm's conditional save cursor depending
|
// Mode 1048 is xterm's conditional save cursor depending
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue