202 Commits

Author SHA1 Message Date
Chinmay Dalal
bccf1216bc exit early when cursor is on a prompt line 2023-10-30 12:42:58 +05:30
Chinmay Dalal
0920ab08cd handle cursor on a prompt line 2023-10-30 11:52:35 +05:30
Chinmay Dalal
3ff20c7418 add tests 2023-10-30 10:19:21 +05:30
Chinmay Dalal
fae356be5a implement selecting output a ScreenPoint is in
This works by finding prompt markers provided by shell integration
Does not yet close #752 as this is not exposed
2023-10-30 01:30:43 +05:30
Mitchell Hashimoto
4ed6112e6d move circular buffer to src/ 2023-10-24 15:27:16 -07:00
Mitchell Hashimoto
06f7cfb398 terminal: save cursor and restore cursor xterm audit 2023-10-15 21:25:47 -07:00
Mitchell Hashimoto
3cc0cbcc9d terminal: SU, fix DL bug 2023-10-10 13:00:00 -07:00
Mitchell Hashimoto
76bbb7c361 terminal: insert lines (IL) handles left/right scroll regions 2023-10-08 20:51:00 -07:00
Mitchell Hashimoto
fa73fa0de2 terminal: ECH handles protection attributes properly 2023-10-07 22:36:29 -07:00
Mitchell Hashimoto
9e506ac7e1 terminal: cursor back handles reverse wrap (mode 45) 2023-10-06 08:35:02 -07:00
Mitchell Hashimoto
6fd082ed63 terminal: scroll region scroll up copied the wrong length of data
Fixes #315

This function has various cases that can be hit depending on the state
of the underlying circular buffer. It is a very well tested function but
this particular branch wasn't tested and unsurprisingly turns out there
is a bug in it.

Consider the following circular buffer state representing a terminal
screen with 1 column, 5 rows. Assume the circular buffer representing
this screen is such that `head == tail` and `head = 4` (zero-indexed,
full buffer size is 5). The head and tail are shown with an arrow below.

┌───────────────────────────────────────────────────────────────┐
│                               B                               │
├───────────────────────────────────────────────────────────────┤
│                               C                               │
├───────────────────────────────────────────────────────────────┤
│                               D                               │
├───────────────────────────────────────────────────────────────┤
│                               E                               │
├───────────────────────────────────────────────────────────────┤ ◀───  Head
│                               A                               │       Tail
└───────────────────────────────────────────────────────────────┘

The screen contents are "A B C D E" with each character on a new line.

Next, we set a scroll region from y=0 to y=3 (len=4). The scroll region
contents are "A B C D". Next, we issue a "delete lines" command with
n=2 (`CSI 2 M`) while the cursor is at the top-left corner. The delete
lines command deletes the given number of lines (n=2 in this case) and
shifts the remaining lines up. It does this only within the context
of the scroll region. Therefore, for `CSI 2 M` we would expect our
screen to become "C D _ _ E" (A, B are deleted, C, D shift up, and
E is untouched because its outside of the scroll region).

When executing this operation, we request the memory regions containing
the scroll region. This results in two pointers and lengths. For our
circular buffer state, we get the following:

┌───────────────────────────────────────────────────────────────┐ ◀──── ptr0
│                               A                               │
└───────────────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────┐ ◀──── ptr1
│                               B                               │
├───────────────────────────────────────────────────────────────┤
│                               C                               │
├───────────────────────────────────────────────────────────────┤
│                               D                               │
└───────────────────────────────────────────────────────────────┘

We get two pointers because our circular buffer wraps around the bottom.
The diagram above shows them in top/bottom order not in memory order
(The value of `ptr0 > ptr1` but it doesn't matter for the bug).

The way the math works is as follows:

  1. We calculate the number of lines we need to shift up. That
     value is `height - n`. Our height is 4 (scroll region height) and
     our n is 2 (`CSI 2 M`), so we know we're shifting up 2 lines.
     Let's call this `shift_lines`.

  2. Our start copy offset is `n` because the lines we are retaining
     are exactly after the `n` we're deleting (i.e. we're deleting 2
     lines so the start of the lines we're shifting up is the 3rd line).
     Let's call this `start_offset`.

  3. We realize that our start offset is greater than the size of ptr0,
     so we must be copy from ptr1 into ptr0. Further, we know our start
     offset into ptr1 must be `start_offset - ptr0.len`.
     Let's call this `start_offset_ptr1 = 1`.

  4. Copy `ptr1[start_offset_ptr1]` to `ptr0`. We copy up to
     `shift_lines` amount. `shift_lines` is 2 but `ptr0.len` is only
     `1`. So, we actually copy `@min(shift_lines, ptr0.len)` and have
     `1` line remaining.
     Let's call that `remaining = 1`.

  5. Copy `remaining` from `ptr1[ptr0.len]` to `ptr1`.

  6. Next we need to zero our remaining lines. Our slices only contain
     our scroll region so we know we can zero the memory from
     `ptr1[remaining]` to the end of `ptr1`. We know this because step 5
     only copied `remaining` bytes.

The end result looks like this:

┌───────────────────────────────────────────────────────────────┐ ◀──── ptr[0]
│                               C                               │
└───────────────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────┐ ◀──── ptr[1]
│                               D                               │
├───────────────────────────────────────────────────────────────┤
│                                                               │
├───────────────────────────────────────────────────────────────┤
│                                                               │
└───────────────────────────────────────────────────────────────┘

The bug was in step 6. We were incorrectly zeroing from `start_offset_ptr1`
instead of `remaining`. This was just a simple typo. The results are
devastating, but only under the exactly correct circumstances (those
in this commit message). In that scenario, the bug produced the
following:

┌───────────────────────────────────────────────────────────────┐ ◀────────── ptr[0]
│                               C                               │
└───────────────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────────────┐ ◀────────── ptr[1]
│                               D                               │
├───────────────────────────────────────────────────────────────┤
│                               C                               │
├───────────────────────────────────────────────────────────────┤
│                                                               │
└───────────────────────────────────────────────────────────────┘

Notice the incorrect "C" that remains and is not zeroed.

This example showed a scenario with 1 column and leaving only 1 line out
of the scroll region. The real bug in #315 would often mistakingly leave
multiple lines in the scroll region. The effect was that scrolling
produced garbage lines because you'd "scroll" and part of what should've
scrolled would remain.

This garbage state was only in the terminal screen state, so it didn't
impact actual programs running or their data (i.e. vim). But, it made
the program unusable.
2023-09-28 21:10:37 -07:00
Tim Culverhouse
6b1d99dc6e terminal: rows created from IND should inherit the current bg attr
Any row created from scrolling via IND ("\x1BD") should have it's
background set as the current background. This can be verified in any
terminal with

  $ echo -e "\x1B[41m" && cat -v"

Followed by pressing enter to scroll the screen. We expect to see red
rows appear. Add test case to verify.

Fixes: alacritty/vim_large_screen_scroll
2023-09-26 22:10:05 -05:00
Tim Culverhouse
cfdce572b9 screen: only use bg attr for inserted rows
When scrolling up or deleting lines (effectively the same operation),
the inserted lines should only inherit the bg attribute of the cursor.
This behavior is similar to erase display and erase line. Update tests
to reflect this behavior.
2023-09-25 16:07:48 -05:00
Mitchell Hashimoto
2a390785f5 terminal: add protected mode flag to cursor pen 2023-09-25 10:56:57 -07:00
Tim Culverhouse
66875206bb terminal: move charset to screen
Each screen (primary and alternate) retains the state of the current
charset when DECSC (save cursor) is called. Move the CharsetState into
the screen to enable saving the state with each screen.

Add a test for charset state on screen change
2023-09-25 10:43:39 -05:00
Mitchell Hashimoto
d9cfd00e9f Big Cursor State Refactor
This makes a few major changes:

  - cursor style on terminal is single source of stylistic truth
  - cursor style is split between style and style request
  - cursor blinking is handled by the renderer thread
  - cursor style/visibility is no longer stored as persistent state on
    renderers
  - cursor style computation is extracted to be shared by all renderers
  - mode 12 "cursor_blinking" is now source of truth on whether blinking
    is enabled or not
  - CSI q and mode 12 are synced like xterm
2023-09-09 20:19:37 -07:00
Mitchell Hashimoto
cdf81b610d terminal: mark prompt continuation lines, end prompt clear at first
prompt
2023-09-03 14:00:56 -07:00
Mitchell Hashimoto
65246327dd terminal: add more assertions 2023-08-31 19:45:22 -07:00
Mitchell Hashimoto
0aebf1e406 terminal: CSI S allows for count greater than scroll region height 2023-08-31 17:52:22 -07:00
Mitchell Hashimoto
3352cae3f7 terminal: resize more cols no longer preserves trailing stylized cells 2023-08-30 15:55:43 -07:00
Mitchell Hashimoto
ed5c001690 font/shaper: split ligature around cell style change 2023-08-29 14:09:21 -07:00
Mitchell Hashimoto
be27b825f3 terminal: resize with less cols preserves zero width codepoints 2023-08-28 08:18:03 -07:00
Mitchell Hashimoto
c243c9d72e terminal: screen test dumpString function should add graphemes 2023-08-28 08:07:40 -07:00
Mitchell Hashimoto
e6edf3105e font: grapheme clusters need to find a single font for all codepoints
When font shaping grapheme clusters, we erroneously used the font index
of a font that only matches the first codepoint in the cell. This led to the
combining characters being [usually] unknown and rendering as boxes.

For a grapheme, we must find a font face that has a glyph for _all codepoints_
in the grapheme.

This also fixes an issue where we now properly render the unicode replacement
character if we can't find a font satisfying a codepoint.
2023-08-26 09:35:56 -07:00
Mitchell Hashimoto
33c21c7339 terminal: mark kitty images as dirty on resize 2023-08-22 14:46:23 -07:00
Mitchell Hashimoto
5a9bbcbc2d renderer/metal: clip image if necessary off top of viewport (scrolling) 2023-08-22 11:32:45 -07:00
Mitchell Hashimoto
80c7f09a36 terminal/kitty-gfx: start terminal state, can load and add images 2023-08-20 22:03:21 -07:00
Mitchell Hashimoto
a9d7e0eb7f terminal: parse kitty query, push, pop keyboard flags 2023-08-16 17:31:05 -07:00
Mitchell Hashimoto
9e27dcdec9 font: shaper doesn't split run on selection if selection splits grapheme 2023-08-15 15:32:10 -07:00
Mitchell Hashimoto
c8d1745791 terminal: selection string must include grapheme data 2023-08-15 14:55:43 -07:00
Mitchell Hashimoto
67fb8d9bd4 terminal: do not crash if selecting a wide spacer on a soft-wrapped line 2023-08-15 14:38:13 -07:00
Mitchell Hashimoto
6a4b25714a terminal: add a test to verify our grapheme state is what we expect 2023-08-15 13:55:35 -07:00
Mitchell Hashimoto
63fa34ef6b terminal: avoid underflow on resize, tests added 2023-08-12 11:30:07 -07:00
Mitchell Hashimoto
71c8d5fc8e terminal: resizing to 1 col wide with wide chars 2023-08-12 10:23:06 -07:00
Mitchell Hashimoto
44dd51a5b9 terminal: less col resizing with wide char needs to insert head spacer 2023-08-12 10:07:13 -07:00
Mitchell Hashimoto
eb10e9642c terminal: introduce wide spacer head if reflowing wide char w/ more cols 2023-08-12 09:51:33 -07:00
Mitchell Hashimoto
3d5eda62fe terminal: resize more cols with wide spacer head across multiple lines 2023-08-12 08:26:13 -07:00
Mitchell Hashimoto
a6af75aee4 terminal: resize more cols with wide spacer head deletes the spacer 2023-08-12 08:20:10 -07:00
Mitchell Hashimoto
3d72178ef4 terminal: delete wide char if it wraps and we delete the row above 2023-08-11 16:23:02 -07:00
Mitchell Hashimoto
8bb69045a8 terminal: allow selections outside of written area and clamp
This fixes a possible crash.
2023-08-11 14:21:07 -07:00
Kevin Hovsäter
22b8173164 Fix typos 2023-08-08 14:27:34 +02:00
Mitchell Hashimoto
a890cc3a5b terminal: add screen.dumpString 2023-07-09 11:52:37 -07:00
Mitchell Hashimoto
de66d4925a terminal: rename scroll "delta/delta_no_grow" to screen/viewport 2023-07-08 13:47:16 -07:00
Mitchell Hashimoto
1a94f6ba7d terminal: do not scroll viewport if new lines are added while scrolled 2023-07-08 13:42:00 -07:00
Mitchell Hashimoto
b3b19997ea terminal: scroll to row always tries to get it to the top 2023-07-06 10:31:47 -07:00
Mitchell Hashimoto
9f86c48fd8 keybinding jump_to_prompt for semantic prompts 2023-07-06 10:30:29 -07:00
Mitchell Hashimoto
b542f7e3c4 terminal: jump to prompt core methods 2023-07-06 10:16:07 -07:00
Mitchell Hashimoto
738c4dff4c clear_screen keybinding works even when not at shell prompt
Instead of sending formfeed (0x0C), clear_screen actually does a
terminal emulator level clear instead. This MOSTLY matches the behavior
of iTerm and Terminal.app, with some differences:

  1. I do not clear _below_ the cursor. I feel like the use case for
     this feature is primarily to clear above the cursor. Happy to be
     wrong here but I want it proven to me!

  2. I do not clear in alternate screen mode. Clearing alt screens
     breaks rendering in Vim, less, etc. and it feels like the wrong
     behavior.
2023-07-05 14:01:01 -07:00
Mitchell Hashimoto
314f9287b1 Update Zig (#164)
* update zig

* pkg/fontconfig: clean up @as

* pkg/freetype,harfbuzz: clean up @as

* pkg/imgui: clean up @as

* pkg/macos: clean up @as

* pkg/pixman,utf8proc: clean up @as

* clean up @as

* lots more @as cleanup

* undo flatpak changes

* clean up @as
2023-06-30 12:15:31 -07:00
Mitchell Hashimoto
56f8e39e5b Update zig, mach, fmt 2023-06-25 11:08:20 -07:00