640 Commits

Author SHA1 Message Date
Mitchell Hashimoto
7a8f2bfed6 terminal: decscusr 2023-10-10 12:24:11 -07:00
Mitchell Hashimoto
f216609662 terminal: RIS should reset tabstops, ESC ? W should reset every 8
Fixes #648

Two issues here:

  - RIS should've been resetting the tabstops to every 8, but was
    clearing all tabstops.

  - `ESC ? W` should've reset tabstops to every 8, but was clearing
    all tabstops.
2023-10-10 09:02:22 -07:00
Mitchell Hashimoto
2354454907 terminal: set left and right margins, left and right margin mode 69 2023-10-09 21:20:15 -07:00
Mitchell Hashimoto
be99d8ffe1 terminal: decaln 2023-10-09 20:33:52 -07:00
Mitchell Hashimoto
7cc0bbe211 terminal: set top and bottom margin tests 2023-10-09 20:08:16 -07:00
Mitchell Hashimoto
9c45c6a3d1 terminal: handle ansi vs dec mode
Previously, we just ignored ansi vs dec modes (`?`-prefix) and just
responded to both requests most of the time using the number as the
unique value. This _kind of works_ because almost all DEC modes do not
overlap with ANSI modes, but some overlap (i.e. `insert`, ANSI mode 4).

This commit properly separates ANSI vs DEC modes and updates all of our
terminal sequences to handle both (where applicable -- some sequences
are explicitly DEC-only).
2023-10-09 16:01:08 -07:00
Mitchell Hashimoto
0e22e2a8dd terminal: SD should also work if cursor outside of left/right region 2023-10-09 10:53:47 -07:00
Mitchell Hashimoto
fc08f9ab17 terminal: TBC tests 2023-10-09 10:01:23 -07:00
Mitchell Hashimoto
ed23f2f1d0 terminal: implement DECID (ESC Z) 2023-10-09 09:43:28 -07:00
Mitchell Hashimoto
773104d343 terminal: scroll down tests 2023-10-09 09:40:28 -07:00
Mitchell Hashimoto
d0b8bf7752 terminal: enable alternate scroll mode by default
Fixes #641

xterm does not so there is an argument to not doing this but a lot of
other terminals do. Having this on by default makes things like less
scroll with the mouse wheel by default which is nice to have.
2023-10-09 09:23:39 -07:00
Mitchell Hashimoto
60f0e9289a terminal: dch xterm audit 2023-10-08 22:16:35 -07:00
Mitchell Hashimoto
1176b65a95 terminal: test IND preserves background sgr 2023-10-08 21:39:29 -07:00
Mitchell Hashimoto
4b9560aa31 terminal: DL 2023-10-08 21:28:41 -07:00
Mitchell Hashimoto
76bbb7c361 terminal: insert lines (IL) handles left/right scroll regions 2023-10-08 20:51:00 -07:00
Mitchell Hashimoto
38f968e368 terminal: IL preserves bg sgr, partial left/right margin support 2023-10-08 15:27:09 -07:00
Mitchell Hashimoto
eab390344a terminal: ED xterm audit
Fix multi-cell handling
Test all scenarios
2023-10-08 14:48:06 -07:00
Mitchell Hashimoto
02b134f97e terminal: EL (erase line) xterm audit
Fix multi-cell char handling
Fix bg SGR respecting in non-protected cases
Fix protected attribute logic
2023-10-08 09:03:04 -07:00
Mitchell Hashimoto
fa73fa0de2 terminal: ECH handles protection attributes properly 2023-10-07 22:36:29 -07:00
Mitchell Hashimoto
514071dd87 terminal: ECH tests with bg and multi-cell fix 2023-10-07 22:21:38 -07:00
Mitchell Hashimoto
d85baa4631 terminal: alternate scroll (mode 1007) should not be enabled by default 2023-10-07 14:26:11 -07:00
Mitchell Hashimoto
b927760149 terminal: HPR, VPR 2023-10-07 09:32:58 -07:00
Mitchell Hashimoto
f5a5de15cc terminal: HPA, VPA 2023-10-07 09:22:13 -07:00
Mitchell Hashimoto
28f6379453 terminal: CUP respects left/right scroll region 2023-10-07 09:17:00 -07:00
Mitchell Hashimoto
c089c37b90 terminal: CUF handles right margin 2023-10-07 08:42:08 -07:00
Mitchell Hashimoto
9b7c778e55 terminal: cursor up respects scroll margins 2023-10-06 22:41:40 -07:00
Mitchell Hashimoto
78d69c6cdb website: ich split multi-cell 2023-10-06 22:23:08 -07:00
Mitchell Hashimoto
0645ab7a98 terminal: ICH handles left/right margins, clears bg 2023-10-06 22:08:21 -07:00
Mitchell Hashimoto
e4b844dea6 terminal: CHT 2023-10-06 16:58:48 -07:00
Mitchell Hashimoto
cf01cd87a4 terminal: CBT respects left margin in origin mode 2023-10-06 15:48:05 -07:00
Mitchell Hashimoto
6958978a6c terminal: IND supports left/right margins 2023-10-06 14:54:40 -07:00
Mitchell Hashimoto
ec854a20eb terminal: a lot more index tests 2023-10-06 14:33:02 -07:00
Mitchell Hashimoto
eeecc6c7e7 terminal: cursor down respects bottom margins 2023-10-06 12:54:02 -07:00
Mitchell Hashimoto
c2af7b60d0 terminal: FF (0x0D) also invokes LF 2023-10-06 12:00:18 -07:00
Mitchell Hashimoto
3360a88768 terminal: implement origin mode and left margin handling for CR 2023-10-06 11:37:50 -07:00
Mitchell Hashimoto
e3b455444d terminal: have left/right scrolling region data but can't be set yet 2023-10-06 11:28:20 -07:00
Mitchell Hashimoto
f32ae27660 terminal: add todo for CUB for left/right margins 2023-10-06 09:27:02 -07:00
Mitchell Hashimoto
d3483a8eed terminal: extended reverse wrap takes priority over reverse wrap 2023-10-06 08:59:22 -07:00
Mitchell Hashimoto
a1becf73ad terminal: CUB extended reverse wrap mode 2023-10-06 08:55:09 -07:00
Mitchell Hashimoto
9e506ac7e1 terminal: cursor back handles reverse wrap (mode 45) 2023-10-06 08:35:02 -07:00
Mitchell Hashimoto
7fe1a61ae8 terminal: cursor back should reduce count if pending wrap is one 2023-10-06 07:52:15 -07:00
Mitchell Hashimoto
5f96adb993 terminal: mode 2027 2023-10-02 09:34:43 -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
Mitchell Hashimoto
8208947290 termio/exec: hook up xtgettcap 2023-09-27 14:27:56 -07:00
Mitchell Hashimoto
823f47f695 termio: hook up dcs callbacks 2023-09-27 13:32:00 -07:00
Mitchell Hashimoto
032fcee9ff terminal: DCS handler, XTGETTCAP parsing 2023-09-27 12:07:31 -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
Mitchell Hashimoto
3f48a43ba4 terminal: cursors must set pending wrap 2023-09-25 17:42:37 -07:00
Mitchell Hashimoto
2c26071332 terminal: eraseLine resets wrap 2023-09-25 17:32:51 -07:00
Mitchell Hashimoto
1f3138add7 terminal: eraseChars resets wrap 2023-09-25 16:23:29 -07:00