See #5930
Kakoune sends a real SGR sequence with 17 parameters. Our previous max
was 16 so we through away the entire sequence. This commit increases the
max rather than fundamentally addressing limitations.
Practically, it took us this long to witness a real world sequence that
exceeded our previous limit. We may need to revisit this in the future,
but this is an easy fix for now.
In the future, as the comment states in this diff, we should probably
look into a rare slow path where we heap allocate to accept up to some
larger size (but still would need a cap to avoid DoS). For now,
increasing to 24 slightly increases our memory usage but shouldn't
result in any real world issues.
Fixes#5718
When a terminal is resized with text reflow (i.e. soft-wrapped text), the cursor
is generally reflowed with it.
For example, imagine a terminal window 5-columns wide and you type the
following without pressing enter. The cursor is on the X.
```
OOOOO
OOX
```
If you resize the window now to 8 or more columns, this happens, as expected:
```
OOOOOOOX
```
As expected, the cursor remains on the "X". This behaves like any other text
input...
Terminals also provide an escape sequence to
[save the cursor (ESC 7 aka DECSC)](https://ghostty.org/docs/vt/esc/decsc).
This includes, amongst other things, the cursor position. The cursor can be
restored with [DECRC](https://ghostty.org/docs/vt/esc/decrc).
The behavior of the position of the _saved cursor_ in the context of text
reflow is unspecified and varies wildly between terminals Ghostty does this
right now (as do many other terminals):
```
OOOOOOOO
X
```
This commit changes the behavior so that we reflow the saved cursor.
Fully reset the kitty image storage instead of using the delete handler,
previously this caused a memory corruption / likely segfault due to use
of undefined, since the delete handler tries to clear the tracked pins
for placements, which it gets from the terminal, for which `undefined`
was passed in before.
Previously assumed adjusted capacities would always fit the cursor style
and hyperlink, this is not necessarily the case and led to memory
corruption in scenarios with large hyperlinks.
Fixes#5022
The CSI SGR sequence (CSI m) is unique in that its the only CSI sequence
that allows colons as delimiters between some parameters, and the colon
vs. semicolon changes the semantics of the parameters.
Previously, Ghostty assumed that an SGR sequence was either all colons
or all semicolons, and would change its behavior based on the first
delimiter it encountered.
This is incorrect. It is perfectly valid for an SGR sequence to have
both colons and semicolons as delimiters. For example, Kakoune sends
the following:
;4:3;38;2;175;175;215;58:2::190:80:70m
This is equivalent to:
- unset (0)
- curly underline (4:3)
- foreground color (38;2;175;175;215)
- underline color (58:2::190:80:70)
This commit changes the behavior of Ghostty to track the delimiter per
parameter, rather than per sequence. It also updates the SGR parser to
be more robust and handle the various edge cases that can occur. Tests
were added for the new cases.
Related to #4485
This commit matches ConEmu's parsing logic[^1] more faithfully. For any
substate that requires a progress, ConEmu parses so long as there is a
number and then just ignores the rest.
For substates that don't require a progress, ConEmu literally ignores
everything after the state.
Tests cover both.
[^1]: 740b09c363/src/ConEmuCD/ConAnsiImpl.cpp (L2264)
Extracted from #3110
Initial fix is relatively basic, and catching it with a test only
required a little bit of extra scrutiny of the cursor state after one of
the tests that we already had.
However, the fix revealed faulty dirty tracking logic throughout the
`cursorScrollAbove` function (and therefore bad results that were being
tested for when they should not have been). I've ended up clarifying
things, fixing the asserted dirty states in all the `cursorScrollAbove`
tests, and then finally implementing another very trivial fix that
catches the mistake.
Fixing the dirty tracking is really just an exercise in correctness
though, since when the scroll happens it inherently invalidates the
viewport, and therefore will trigger a full rebuild in the renderer...
unless, I guess, another operation is performed that cancels things out
and results in the viewport pin being in the same place as the previous
render, but that seems an exceptionally difficult scenario to make
happen on purpose much less accidentally.
This PR is almost entirely changes to comments and tests, there are only
2 lines of real code it changes, the one added to the start of
`cursorScrollAbove` and the one modified at the start of
`cursorScrollAboveRotate`. I believe these changes are entirely safe. (I
wonder if they might have a bad effect on our `vtebench` scrolling
performance though...)
Accounts for improved behavior due to prior memory corruption fix for
`cursorScrollAboveRotate` and reveals a new problem in a different
`cursorScrollAbove` sub-function.
Unless it's guaranteed that the new pin is in the same page as the old
one, `cursor.page_pin` should only be updated through `cursorChangePin`,
not directly.
We call `cursorChangePin` which may invalidate the provided pin if it
needs to adjust the page capacity, and as such we should consider the
pin we pass in to it invalid afterwards, and access it through cursor
instead.
Fixes#3119
Supersedes #3099
ConEmu and iTerm2 both use OSC 9 to implement different things. iTerm2
uses it to implement desktop notifications, while ConEmu uses it to
implement various OS commands.
Ghostty has supported iTerm2 OSC 9 for a while, but it didn't (and
doesn't) support ConEmu OSC 9. This means that if a program tries to
send a ConEmu OSC 9 to Ghostty, it will turn into a desktop
notification.
This commit adds parsing for ConEmu OSC 9 progress reports. This means
that these specific syntaxes can never be desktop notifications, but
they're quite strange to be desktop notifications anyway so this should
be an okay tradeoff.
This doesn't actually _do anything with the progress reports_, it just
parses them so that they don't turn into desktop notifications.
cc @Jan200101
Fixes#3119
ConEmu and iTerm2 both use OSC 9 to implement different things. iTerm2
uses it to implement desktop notifications, while ConEmu uses it to
implement various OS commands.
Ghostty has supported iTerm2 OSC 9 for a while, but it didn't (and
doesn't) support ConEmu OSC 9. This means that if a program tries to
send a ConEmu OSC 9 to Ghostty, it will turn into a desktop notification.
This commit adds parsing for ConEmu OSC 9 progress reports. This means
that these specific syntaxes can never be desktop notifications, but
they're quite strange to be desktop notifications anyway so this should
be an okay tradeoff.
This doesn't actually _do anything with the progress reports_, it just
parses them so that they don't turn into desktop notifications.