diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index bbca660cb..9332c5479 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -1573,6 +1573,11 @@ pub fn insertBlanks(self: *Terminal, count: usize) void { // This is the index of the final copyable value that we need to copy. const copyable_end = start + copyable - 1; + // If our last cell we're shifting is wide, then we need to clear + // it to be empty so we don't split the multi-cell char. + const cell = row.getCellPtr(copyable_end); + if (cell.attrs.wide) cell.char = 0; + // Shift count cells. We have to do this backwards since we're not // allocated new space, otherwise we'll copy duplicates. var i: usize = 0; @@ -3949,6 +3954,23 @@ test "Terminal: insertBlanks shift off screen" { } } +test "Terminal: insertBlanks split multi-cell character" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 10); + defer t.deinit(alloc); + + for ("123") |c| try t.print(c); + try t.print('橋'); + t.setCursorPos(1, 1); + t.insertBlanks(1); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings(" 123", str); + } +} + test "Terminal: insertBlanks inside left/right scroll region" { const alloc = testing.allocator; var t = try init(alloc, 10, 10); @@ -4073,6 +4095,24 @@ test "Terminal: insert mode with wide characters at end" { } } +test "Terminal: insert mode pushing off wide character" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 2); + defer t.deinit(alloc); + + for ("123") |c| try t.print(c); + try t.print('😀'); // 0x1F600 + t.modes.set(.insert, true); + t.setCursorPos(1, 1); + try t.print('X'); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("X123", str); + } +} + test "Terminal: cursorIsAtPrompt" { const alloc = testing.allocator; var t = try init(alloc, 3, 2); diff --git a/website/app/vt/modes/insert/page.mdx b/website/app/vt/modes/insert/page.mdx new file mode 100644 index 000000000..1a1b6b9a0 --- /dev/null +++ b/website/app/vt/modes/insert/page.mdx @@ -0,0 +1,89 @@ +import VTMode from "@/components/VTMode"; + +# Insert + + + +When enabled, text is written to the cell under the cursor +and all existing content is shifted right. When disabled, text +overwrites existing content. + +This mode is unset as part of both [full reset (RIS)](/vt/ris) +and [soft reset (DECSTR)](/vt/decstr). + +If a multi-cell character (such as "橋") is shifted so that the cell is split +in half, the multi-cell character can either be clipped or erased. + +This mode is typically disabled on terminal startup. + +## Validation + +### INSERT V-1: Simple Usage + +```bash +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "123456" +printf "\033[1G" +printf "\033[4h" +printf "ABC" +``` + +``` +|ABC123456_| +``` + +### INSERT V-2: Pushing Off the Screen Edge + +```bash +cols=$(tput cols) +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "\033[${cols}G" +printf "\033[6D" +printf "123456" +printf "\033[6D" +printf "\033[4h" +printf "ABC" +``` + +``` +|____ABC1234| +``` + +### INSERT V-3: Writing on the Screen Edge + +```bash +cols=$(tput cols) +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "\033[${cols}G" +printf "\033[6D" +printf "123456" +printf "\033[1D" +printf "\033[4h" +printf "ABC" +``` + +``` +|____12345AB| +|Cc_________| +``` + +### INSERT V-3: Splitting a Multi-Cell Character + +```bash +cols=$(tput cols) +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "\033[${cols}G" +printf "\033[6D" +printf "1234橋" +printf "\033[6D" +printf "\033[4h" +printf "A" +``` + +``` +|_____A1234_| +``` diff --git a/website/app/vt/modes/kam/page.mdx b/website/app/vt/modes/kam/page.mdx index 3efeca79c..dfab83e9e 100644 --- a/website/app/vt/modes/kam/page.mdx +++ b/website/app/vt/modes/kam/page.mdx @@ -13,6 +13,8 @@ A poorly behaved terminal program can lock the terminal emulator using this command. Terminal emulators should provide a mechanism to reset this or outright disable it. +This mode is typically disabled on terminal startup. + ## Validation ### KAM V-1: Disable Keyboard Input diff --git a/website/components/VTMode.tsx b/website/components/VTMode.tsx index b6c690071..7287c1c87 100644 --- a/website/components/VTMode.tsx +++ b/website/components/VTMode.tsx @@ -9,7 +9,7 @@ export default function VTMode({
- {ansi ? "?" : ""} + {ansi ? "" : "?"} {value}