mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
terminal: spacer heads should only exist w/o l/r margin
This commit is contained in:
@ -218,7 +218,7 @@ pub fn printRepeat(self: *Terminal, count_req: usize) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(self: *Terminal, c: u21) !void {
|
pub fn print(self: *Terminal, c: u21) !void {
|
||||||
// log.debug("print={x} y={} x={}", .{ c, self.screen.cursor.y, self.screen.cursor.x });
|
log.debug("print={x} y={} x={}", .{ c, self.screen.cursor.y, self.screen.cursor.x });
|
||||||
|
|
||||||
// If we're not on the main display, do nothing for now
|
// If we're not on the main display, do nothing for now
|
||||||
if (self.status_display != .main) return;
|
if (self.status_display != .main) return;
|
||||||
@ -316,7 +316,10 @@ pub fn print(self: *Terminal, c: u21) !void {
|
|||||||
// char as normal.
|
// char as normal.
|
||||||
if (self.screen.cursor.x == right_limit - 1) {
|
if (self.screen.cursor.x == right_limit - 1) {
|
||||||
if (!self.modes.get(.wraparound)) return;
|
if (!self.modes.get(.wraparound)) return;
|
||||||
self.printCell(' ', .spacer_head);
|
self.printCell(
|
||||||
|
' ',
|
||||||
|
if (right_limit == self.cols) .spacer_head else .narrow,
|
||||||
|
);
|
||||||
try self.printWrap();
|
try self.printWrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +445,10 @@ pub fn print(self: *Terminal, c: u21) !void {
|
|||||||
// how xterm behaves.
|
// how xterm behaves.
|
||||||
if (!self.modes.get(.wraparound)) return;
|
if (!self.modes.get(.wraparound)) return;
|
||||||
|
|
||||||
self.printCell(' ', .spacer_head);
|
// We only create a spacer head if we're at the real edge
|
||||||
|
// of the screen. Otherwise, we clear the space with a narrow.
|
||||||
|
// This allows soft wrapping to work correctly.
|
||||||
|
self.printCell(' ', if (right_limit == self.cols) .spacer_head else .narrow);
|
||||||
try self.printWrap();
|
try self.printWrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +625,11 @@ fn printCell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn printWrap(self: *Terminal) !void {
|
fn printWrap(self: *Terminal) !void {
|
||||||
self.screen.cursor.page_row.wrap = true;
|
// We only mark that we soft-wrapped if we're at the edge of our
|
||||||
|
// full screen. We don't mark the row as wrapped if we're in the
|
||||||
|
// middle due to a right margin.
|
||||||
|
const mark_wrap = self.screen.cursor.x == self.cols - 1;
|
||||||
|
if (mark_wrap) self.screen.cursor.page_row.wrap = true;
|
||||||
|
|
||||||
// Get the old semantic prompt so we can extend it to the next
|
// Get the old semantic prompt so we can extend it to the next
|
||||||
// line. We need to do this before we index() because we may
|
// line. We need to do this before we index() because we may
|
||||||
@ -630,9 +640,11 @@ fn printWrap(self: *Terminal) !void {
|
|||||||
try self.index();
|
try self.index();
|
||||||
self.screen.cursorHorizontalAbsolute(self.scrolling_region.left);
|
self.screen.cursorHorizontalAbsolute(self.scrolling_region.left);
|
||||||
|
|
||||||
// New line must inherit semantic prompt of the old line
|
if (mark_wrap) {
|
||||||
self.screen.cursor.page_row.semantic_prompt = old_prompt;
|
// New line must inherit semantic prompt of the old line
|
||||||
self.screen.cursor.page_row.wrap_continuation = true;
|
self.screen.cursor.page_row.semantic_prompt = old_prompt;
|
||||||
|
self.screen.cursor.page_row.wrap_continuation = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Assure that our screen is consistent
|
// Assure that our screen is consistent
|
||||||
self.screen.assertIntegrity();
|
self.screen.assertIntegrity();
|
||||||
@ -2426,6 +2438,33 @@ test "Terminal: print wide char" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Terminal: print wide char at edge creates spacer head" {
|
||||||
|
var t = try init(testing.allocator, .{ .cols = 10, .rows = 10 });
|
||||||
|
defer t.deinit(testing.allocator);
|
||||||
|
|
||||||
|
t.setCursorPos(1, 10);
|
||||||
|
try t.print(0x1F600); // Smiley face
|
||||||
|
try testing.expectEqual(@as(usize, 1), t.screen.cursor.y);
|
||||||
|
try testing.expectEqual(@as(usize, 2), t.screen.cursor.x);
|
||||||
|
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 9, .y = 0 } }).?;
|
||||||
|
const cell = list_cell.cell;
|
||||||
|
try testing.expectEqual(Cell.Wide.spacer_head, cell.wide);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 0, .y = 1 } }).?;
|
||||||
|
const cell = list_cell.cell;
|
||||||
|
try testing.expectEqual(@as(u21, 0x1F600), cell.content.codepoint);
|
||||||
|
try testing.expectEqual(Cell.Wide.wide, cell.wide);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 1, .y = 1 } }).?;
|
||||||
|
const cell = list_cell.cell;
|
||||||
|
try testing.expectEqual(Cell.Wide.spacer_tail, cell.wide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "Terminal: print wide char with 1-column width" {
|
test "Terminal: print wide char with 1-column width" {
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
var t = try init(alloc, .{ .cols = 1, .rows = 2 });
|
var t = try init(alloc, .{ .cols = 1, .rows = 2 });
|
||||||
@ -3232,6 +3271,12 @@ test "Terminal: print right margin wrap" {
|
|||||||
defer testing.allocator.free(str);
|
defer testing.allocator.free(str);
|
||||||
try testing.expectEqualStrings("1234X6789\n Y", str);
|
try testing.expectEqualStrings("1234X6789\n Y", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .active = .{ .x = 0, .y = 0 } }).?;
|
||||||
|
const row = list_cell.row;
|
||||||
|
try testing.expect(!row.wrap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Terminal: print right margin outside" {
|
test "Terminal: print right margin outside" {
|
||||||
@ -3268,6 +3313,39 @@ test "Terminal: print right margin outside wrap" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Terminal: print wide char at right margin does not create spacer head" {
|
||||||
|
var t = try init(testing.allocator, .{ .cols = 10, .rows = 10 });
|
||||||
|
defer t.deinit(testing.allocator);
|
||||||
|
|
||||||
|
t.modes.set(.enable_left_and_right_margin, true);
|
||||||
|
t.setLeftAndRightMargin(3, 5);
|
||||||
|
t.setCursorPos(1, 5);
|
||||||
|
try t.print(0x1F600); // Smiley face
|
||||||
|
try testing.expectEqual(@as(usize, 1), t.screen.cursor.y);
|
||||||
|
try testing.expectEqual(@as(usize, 4), t.screen.cursor.x);
|
||||||
|
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 4, .y = 0 } }).?;
|
||||||
|
const cell = list_cell.cell;
|
||||||
|
try testing.expectEqual(@as(u21, ' '), cell.content.codepoint);
|
||||||
|
try testing.expectEqual(Cell.Wide.narrow, cell.wide);
|
||||||
|
|
||||||
|
const row = list_cell.row;
|
||||||
|
try testing.expect(!row.wrap);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 2, .y = 1 } }).?;
|
||||||
|
const cell = list_cell.cell;
|
||||||
|
try testing.expectEqual(@as(u21, 0x1F600), cell.content.codepoint);
|
||||||
|
try testing.expectEqual(Cell.Wide.wide, cell.wide);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 3, .y = 1 } }).?;
|
||||||
|
const cell = list_cell.cell;
|
||||||
|
try testing.expectEqual(Cell.Wide.spacer_tail, cell.wide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "Terminal: linefeed and carriage return" {
|
test "Terminal: linefeed and carriage return" {
|
||||||
var t = try init(testing.allocator, .{ .cols = 80, .rows = 80 });
|
var t = try init(testing.allocator, .{ .cols = 80, .rows = 80 });
|
||||||
defer t.deinit(testing.allocator);
|
defer t.deinit(testing.allocator);
|
||||||
|
@ -262,9 +262,9 @@ pub fn Stream(comptime Handler: type) type {
|
|||||||
for (actions) |action_opt| {
|
for (actions) |action_opt| {
|
||||||
const action = action_opt orelse continue;
|
const action = action_opt orelse continue;
|
||||||
|
|
||||||
// if (action != .print) {
|
if (action != .print) {
|
||||||
// log.info("action: {}", .{action});
|
log.info("action: {}", .{action});
|
||||||
// }
|
}
|
||||||
|
|
||||||
// If this handler handles everything manually then we do nothing
|
// If this handler handles everything manually then we do nothing
|
||||||
// if it can be processed.
|
// if it can be processed.
|
||||||
|
Reference in New Issue
Block a user