This implements private mode 2027 - grapheme cluster processing, as
defined in the "Terminal Unicode Core"[1] specification.
Internally, we just flip the already existing option "grapheme
shaping". Since it's now runtime changeable, we need a copy of it in
the terminal struct, rather than referencing the conf object.
[1]: 13fc5a8993/spec/terminal-unicode-core.tex (L50-L53)
* In all calls to wl_subsurface_set_position()
* (wp_viewport_set_destination() already does this)
* Whenever we use the scale to calculate margins (search box,
scrollback indicator etc)
* Since the scaling factor is stored as a float (and not a double),
use roundf() instead of round()
We don’t support neither 132 column mode, nor smooth scrolling. Thus
it makes little sense to recognize these control condes.
Note that while XTerm does support 132 columns, it is disabled by
default. In this mode, XTerm also doesn’t trigger the
side-effects (i.e. clearing the screen).
Closes#1265
This fixes an issue where selections in the scroll margins were not
detected correctly. This meant they weren’t canceled as they should
have been, which in turn caused a visual glitch where text appeared to
be selected, but were in fact not.
The status value 4 means "permanently reset", as opposed to 2, which
means "reset". The former implies that there's no way to enable the
mode because it's unsupported (but recognized).
Note: this commit also fixes an unrelated typo in CHANGELOG.md.
Indexed color values are stored in the cell attributes as color
indices (into the 256-color table). However, the index from the CSI
was not validated in any way, meaning you can do something like this:
echo -e ‘\e[38:5:1024m CRASH \e[m’
and foot will crash on an out-of-bounds access.
Fix by clamping the color index.
Closes#1111
The other functions that deal with private modes all use 1070 for
term->sixel.use_private_palette. The xterm docs[1] also list this
param as 1070:
> Ps = 1 0 7 0 ⇒ use private color registers for each graphic
Using 1079 seems to have been a mistake in commit 4aa980a6a2.
Fcft no longer uses wchar_t, but plain uint32_t to represent
codepoints.
Since we do a fair amount of string operations in foot, it still makes
sense to use something that actually _is_ a string (or character),
rather than an array of uint32_t.
For this reason, we switch out all wchar_t usage in foot to
char32_t. We also verify, at compile-time, that char32_t used
UTF-32 (which is what fcft expects).
Unfortunately, there are no string functions for char32_t. To avoid
having to re-implement all wcs*() functions, we add a small wrapper
layer of c32*() functions.
These wrapper functions take char32_t arguments, but then simply call
the corresponding wcs*() function.
For this to work, wcs*() must _also_ be UTF-32 compatible. We can
check for the presence of the __STDC_ISO_10646__ macro. If set,
wchar_t is at least 4 bytes and its internal representation is UTF-32.
FreeBSD does *not* define this macro, because its internal wchar_t
representation depends on the current locale. It _does_ use UTF-32
_if_ the current locale is UTF-8.
Since foot enforces UTF-8, we simply need to check if __FreeBSD__ is
defined.
Other fcft API changes:
* fcft_glyph_rasterize() -> fcft_codepoint_rasterize()
* font.space_advance has been removed
* ‘tags’ have been removed from fcft_grapheme_rasterize()
* ‘fcft_log_init()’ removed
* ‘fcft_init()’ and ‘fcft_fini()’ must be explicitly called
When using indexed colors (i.e. SGR 30/40/90/100), store the index
into the cell’s fg/bg attributes, not the actual color value.
This has a couple of consequences:
Color table lookup is now done when rendering. This means a rendered
cell will always reflect the *current* color table, not the color
table that was in use when the cell was printed to.
This simplifies the OSC-4/104 logic, since we no longer need to update
the grid - we just have to damage it to trigger rendering.
Furthermore, this change simplifies the VT parsing, since we no longer
need to do any memory loads (except loading the SGR parameter values),
only writes.
Each cell now tracks it’s current color source:
* default fg/bg
* base16 fg/bg (maps to *both* the regular and bright colors)
* base256 fg/bg
* RGB
Note that we don’t have enough bits to separate the regular from the
bright colors. These _shouldn’t_ be the same, so we ought to be
fine...
Similar to modifyOtherKeys=1 (foot’s default, and only, mode), except
that:
* All modifiers (and not just Ctrl) generate \E[27;m;n~ escapes
* Regular keys (with modifiers) also generate \E[27;m;n~ escapes (for
example, C-h no longer generates ^H, but \E[27;5;104~)
For our keymap based lookups, this is handled by adding
MOD_MODIFY_OTHER_KEYS_STATE<N> variants.
For “generic” keys, we simply adjust the conditions for when to emit a
\E[27;m;n~ escape - the only requirement is that at least one modifier
is active.
This breaks out the scrollback erasing logic for \E[3J from csi.c, and
moves it to the new function term_erase_scrollback(), and changes the
logic to calculate the start and end row (absolute) numbers of the
scrollback, and only iterate those, instead of iterating *all* rows,
filtering out those that are on-screen.
It also adds an intersection range check of the selection range, and
cancels the selection if it touches any of the deleted scrollback
rows.
This fixes a crash when trying to render the next frame, since the
selection now references rows that have been freed.
Closes#633
There has been some confusion whether enabling DECSDM (private mode
80) enables or disables sixel scrolling.
Foot currently enables scrolling when DECSDM is set, and this patch
changes this, such that setting DECSDM now *disables* scrolling.
The confusion is apparently due to a documentation error in the VT340
manual, as described in
https://github.com/dankamongmen/notcurses/issues/1782#issuecomment-863603641.
And that makes sense, in a way: the SDM in DECSDM stands for Sixel
Display Mode. I.e. it stands to reason that enabling that disables
scrolling.
Anyway, this lead to https://github.com/hackerb9/lsix/issues/41, where
it was eventually proven (by testing on a real VT340), that foot, and
a large number of other terminals (including XTerm) has it wrong:
https://github.com/hackerb9/lsix/issues/41#issuecomment-873269599.
This is a fairly new XTerm extension. The reply is on the format:
DCS > | text ST
XTerm replies with ‘text’ = “XTerm(366)”.
Foot replies with ‘text’ = “foot(1.6.4)”
Closes#359
* Rename cursor.style value ‘bar’ to ‘beam’. ‘bar’ remains recognized,
but should eventually be deprecated and then removed.
* Add ‘cursor.beam-thickness’ option, a pt-or-px value specifying the
thickness of the beam cursor. Defaults to 1.5pt.
* Rename (and export) pt_or_px_as_pixels() to
term_pt_or_px_as_pixels()
* Change term_pt_or_px_as_pixels() to round point values instead of
truncating them.
term_print() is called whenever the client application “prints”
something to the grid. It is called for both ASCII and UTF-8
characters, and needs to handle sixels, insert mode and ASCII
vs. graphical charsets.
Since it’s on the hot path, this becomes unnecessarily slow.
This patch adds a “fast” version of term_print(), tailored for the
common case: ASCII characters in non-insert mode, without any sixels
and non-graphical charsets.
A new function, term_update_ascii_printer(), has been added, and must
be called whenever:
* The currently selected charset *index* changes
* The currently selected charset changes (from ASCII to graphical, or
vice verse)
* Sixels are added to the grid
* Sixels are removed from the grid
* Insert mode is enabled/disabled
When enabled (the default), sixels behave much like normal output; the
start where the cursor is, and the cursor moves with the
sixel. I.e. after emitting a sixel the cursor is left after the image;
either to the right, if private mode 8452 is enabled, or otherwise on
the next line. Terminal content is scrolled up if the sixel is larger
than the screen.
When disabled, sixels *always* start at (0,0), the cursor never moves,
and the terminal content never scrolls.
In other words, the ‘disabled’ mode is a much simpler mode.
All we need to do to support both modes is re-write the sixel-emitting
loop to:
* break early if we’re “out of rows”, i.e. we’ve reached the bottom of
the screen.
* not linefeed, or move the cursor when scrolling is disabled
This patch also fixes a bug in the (new) implementation of private
mode 8452.
When emitting a sixel, we may break it up into smaller pieces, to
ensure a single sixel (as tracked internally) does not cross the
scrollback wrap-around.
The code that checked if we should do a linefeed or not, would skip
the linefeed on the last row of *each* such sixel piece. The correct
thing to do is to skip it only on the last row of the *last* piece.
I chose not to fix this bug in a separate patch since doing so would
have meant re-writing it again when implementing private mode 80.
When disabled (the default), the cursor is positioned on a new line
after emitting a sixel image.
When enabled, the cursor is positioned to the right of the sixel
image.
Closes#363
When enabled (the default), sixels use private color registers. That
is, the color palette from the last sixel is *not* re-used.
When disabled, sixels share (i.e. re-use) the same color palette.
Closes#362
Foot previously responded with window local coordinates.
But, XTerm responds with screen *absolute* coordinates. This isn’t
possible under Wayland, thus we now report (0,0) instead. Same as we
do for ‘CSI 13 ; 0 t’.