Commit graph

4501 commits

Author SHA1 Message Date
Daniel Eklöf
cf46acc68f
render: don’t look at glyphs[0]->cols when determining if overflow should be allowed
Use ‘cell_cols’ instead, which is the number of cells we’ll actually
be using.
2021-06-30 18:01:03 +02:00
Craig Barnes
3e74482d6c terminfo: add Tc, setrgbf and setrgbb capabilities
These extensions are used by tmux and neovim, in order to make use
of 24-bit colors without facing the problems that plague the `RGB`
capability.

This should allow 24-bit colors to work "out of the box" in tmux,
without the usual workaround of adding:

    set-option -ga terminal-overrides ",foot*:Tc"

...to ~/.tmux.conf.

See also:

* 18fe2e8dfa (commitcomment-31373962)
* f83c25942d/runtime/doc/term.txt (L123-L139)
* b1a8c0fe02/CHANGES (L988-L989)

Closes #615
2021-06-29 08:55:53 +01:00
Daniel Eklöf
a09f928175
input: ignore ‘unused’ URL key bindings when mapping bindings to current keymap
This is a temporary fix for #614. Long term fix is to remove the
‘replaced’ bindings from the array at config time.
2021-06-28 22:34:52 +02:00
Daniel Eklöf
117e24dbf4
term: destroy: free URLs before free:ing the grids
Fixes use-after-free when destroying a terminal with “live”
URLs (i.e. when URL mode is active).
2021-06-28 22:33:57 +02:00
Craig Barnes
5dca0458a0 log: add LOG_CLASS_NONE and use as initializer for log_level
This means that logging will be completely disabled until log_init()
has been called, which is useful to prevent log spam when running
UNITTEST{} blocks in debug builds.

Note that this doesn't change the default log level at runtime, which
was already being set to LOG_CLASS_INFO in main.c and client.c.

The new log level is also exposed to the command-line interface as
`--log-level=none`, which allows disabling logging entirely.
2021-06-26 22:15:09 +01:00
Daniel Eklöf
0ff8f72a9d
vt: don’t reset utf8proc grapheme state when we’re not at a grapheme break 2021-06-25 20:42:23 +02:00
Daniel Eklöf
d206697001
doc: benchark: laptop results for 1.8.0 2021-06-25 10:56:40 +02:00
Daniel Eklöf
e365ac0b10
doc: benchmark: add --dat to vtebench command line 2021-06-25 10:24:55 +02:00
Daniel Eklöf
2873043865
doc: benchmarks: update desktop results with 1.8.0 2021-06-25 10:23:43 +02:00
Daniel Eklöf
2535cf51db
changelog: add new ‘unreleased’ section 2021-06-25 08:44:41 +02:00
Daniel Eklöf
3d524746cd
Merge branch 'releases/1.8' 2021-06-25 08:44:11 +02:00
Daniel Eklöf
bc6b4d7b8a
generate-version: fix regression where a tagged version was parsed wrong
The regexps didn’t work when the “extra” portion of “git describe” was
missing.
2021-06-25 08:35:41 +02:00
Daniel Eklöf
0a455174f4
meson/pkgbuild: bump version to 1.8.0 2021-06-25 08:24:42 +02:00
Daniel Eklöf
8df5f90474
changelog: prepare for 1.8.0 2021-06-25 08:23:36 +02:00
Daniel Eklöf
20c0650dfd
wayland: regression: properly instantiate CSDs when there’s no decoration manager
* Set win->configure.csd_mode, not win->csd_mode. Otherwise our
  ‘configure’ handler will swap out the CSD_YES we set, for
  CSD_UNKNOWN(?), resulting in no CSDs at all.

* Don’t instantiate the CSDs in wayl_win_init(), let the ‘configure’
  event handler do that. Just like it does when we have a decoration
  manager emitting decoration configure events.
2021-06-24 23:02:40 +02:00
Daniel Eklöf
07128ee905
changelog: spelling; add missing ‘l’ in ‘experimental’ 2021-06-24 22:55:28 +02:00
Daniel Eklöf
2c32d8617a
pkgbuild: add libutf8proc dependency 2021-06-24 20:29:15 +02:00
Daniel Eklöf
ad981930c3
meson: add utf8proc dep to all libraries pulling in terminal.h 2021-06-24 20:29:15 +02:00
Daniel Eklöf
3bad062f8a
vt: utf8: rotate instead of just shifting when updating compose key
This reduces the number of collisions in even more workloads.
2021-06-24 19:36:39 +02:00
Daniel Eklöf
88ce0e4375
vt: improved key hash algorithm -> reduces number of key collisions 2021-06-24 19:18:06 +02:00
Daniel Eklöf
9a7c6bdcf2
term: CELL_COMB_CHARS chars are keys, not indices -> more range is better
Bump the available key range to 30 bits. This helps reduce key
collisions when handling a large amount of grapheme clusters.
2021-06-24 19:15:53 +02:00
Daniel Eklöf
f20956ff1b
composed: insert: require key to be unique 2021-06-24 19:12:25 +02:00
Daniel Eklöf
4a6dea04c2
install: add -Dgrapheme-clustering to the list of custom meson options 2021-06-24 17:57:34 +02:00
Daniel Eklöf
80c2d9d89d
Merge branch 'harfbuzz' 2021-06-24 17:50:55 +02:00
Daniel Eklöf
3f0f5ec3b7
client: add +/-graphemes to version output 2021-06-24 17:50:44 +02:00
Daniel Eklöf
a319ddf094
foot: add +/-graphemes to version output 2021-06-24 17:50:30 +02:00
Daniel Eklöf
4ea7c5b63f
features: add feature_graphemes()
Returns true if we’re compiled with grapheme shaping support, false
otherwise.
2021-06-24 17:50:04 +02:00
Daniel Eklöf
cf101ea300
changelog: describe what (does not) happens when grapheme-shaping=no 2021-06-24 17:36:57 +02:00
Daniel Eklöf
d5d57c1b20
changelog: composed -> combining 2021-06-24 17:36:52 +02:00
Daniel Eklöf
09c4d16232
changelog: put emphasis on ‘opt-in’ as well 2021-06-24 17:33:09 +02:00
Daniel Eklöf
f19797a5af
changelog: updates to “grapheme shaping” 2021-06-24 17:30:50 +02:00
Daniel Eklöf
415ecfc6fa
vt: codespell: bumb -> bump 2021-06-24 17:30:50 +02:00
Daniel Eklöf
fe8ca23cfe
composed: store compose chains in a binary search tree
The previous implementation stored compose chains in a dynamically
allocated array. Adding a chain was easy: resize the array and append
the new chain at the end. Looking up a compose chain given a compose
chain key/index was also easy: just index into the array.

However, searching for a pre-existing chain given a codepoint sequence
was very slow. Since the array wasn’t sorted, we typically had to scan
through the entire array, just to realize that there is no
pre-existing chain, and that we need to add a new one.

Since this happens for *each* codepoint in a grapheme cluster, things
quickly became really slow.

Things were ok:ish as long as the compose chain struct was small, as
that made it possible to hold all the chains in the cache. Once the
number of chains reached a certain point, or when we were forced to
bump maximum number of allowed codepoints in a chain, we started
thrashing the cache and things got much much worse.

So what can we do?

We can’t sort the array, because

a) that would invalidate all existing chain keys in the grid (and
iterating the entire scrollback and updating compose keys is *not* an
option).

b) inserting a chain becomes slow as we need to first find _where_ to
insert it, and then memmove() the rest of the array.

This patch uses a binary search tree to store the chains instead of a
simple array.

The tree is sorted on a “key”, which is the XOR of all codepoints,
truncated to the CELL_COMB_CHARS_HI-CELL_COMB_CHARS_LO range.

The grid now stores CELL_COMB_CHARS_LO+key, instead of
CELL_COMB_CHARS_LO+index.

Since the key is truncated, collisions may occur. This is handled by
incrementing the key by 1.

Lookup is of course slower than before, O(log n) instead of
O(1).

Insertion is slightly slower as well: technically it’s O(log n)
instead of O(1). However, we also need to take into account the
re-allocating the array will occasionally force a full copy of the
array when it cannot simply be growed.

But finding a pre-existing chain is now *much* faster: O(log n)
instead of O(n). In most cases, the first lookup will either
succeed (return a true match), or fail (return NULL). However, since
key collisions are possible, it may also return false matches. This
means we need to verify the contents of the chain before deciding to
use it instead of inserting a new chain. But remember that this
comparison was being done for each and every chain in the previous
implementation.

With lookups being much faster, and in particular, no longer requiring
us to check the chain contents for every singlec chain, we can now use
a dynamically allocated ‘chars’ array in the chain. This was
previously a hardcoded array of 10 chars.

Using a dynamic allocated array means looking in the array is slower,
since we now need two loads: one to load the pointer, and a second to
load _from_ the pointer.

As a result, the base size of a compose chain (i.e. an “empty” chain)
has now been reduced from 48 bytes to 32. A chain with two codepoints
is 40 bytes. This means we have up to 4 codepoints while still using
less, or the same amount, of memory as before.

Furthermore, the Unicode random test (i.e. write random “unicode”
chars) is now **faster** than current master (i.e. before text-shaping
support was added), **with** test-shaping enabled. With text-shaping
disabled, we’re _even_ faster.
2021-06-24 17:30:49 +02:00
Daniel Eklöf
fcd6327297
term: bump compose chain char array to 10 chars
There are some very long sequences out there... e.g. 👩🏼‍❤️‍💋‍👨🏽
2021-06-24 17:30:49 +02:00
Daniel Eklöf
fd70058795
changelog: add a “grapheme shaping” section 2021-06-24 17:30:49 +02:00
Daniel Eklöf
f3e5c3deb9
doc: foot.ini: grapheme-shaping: mention regular compose characters 2021-06-24 17:30:49 +02:00
Daniel Eklöf
b14524215b
render: use cell cols from compose chain, not grapheme
fcft’s view of how many columns a grapheme cluster is may differ from
our own. Make sure the rendered glyph matches the number of columns
that were allocated when the cluster was printed.
2021-06-24 17:30:48 +02:00
Daniel Eklöf
34e85e7726
scripts: generate-alt-random: add emoji sequences 2021-06-24 17:30:48 +02:00
Daniel Eklöf
81131e3a87
vt: utf8: don’t scan *all* previous chains
When checking if we already have a compose chain for the current
sequence of characters, don’t search the list from the beginning,
unless we have to.

Taking the following things into consideration:

* New compose chains are always appended at the end of the list
* If the current sequence is 3 or more characters, it *must* consist
  of an existing compose chain, plus the new character.

Thus, when searching, start at index 0 if we only have two characters,
since then the base cell originally contained a regular base
character, and not a compose chain. I.e. the new chain may be
_anywhere_ in the chain list.

If however we have a sequence of three or more characters, start at
the index the *base* chain was at. If the chain we’re searching for
exists, it *must* have been added *after* the base chain, and thus
it *must* be located *after* the base chain in the chain list.
2021-06-24 17:30:48 +02:00
Daniel Eklöf
e81d1845bf
vt: utf8: de-duplicate; jump to end of function to print to grid 2021-06-24 17:30:48 +02:00
Daniel Eklöf
c0d9f92e1a
render: don’t modify the cell’s x position. Fixes broken underlines 2021-06-24 17:30:47 +02:00
Daniel Eklöf
dc5019a535
vt: utf8-print: don’t build a compose chain on a zero-width base character 2021-06-24 17:30:47 +02:00
Daniel Eklöf
6187aa0b1b
term: lower maximum number of characters in a compose chain
Before the grapheme cluster segmentation work, we limited the number
of combining characters to base+5. I.e. 6 in total.

For a while now, we’ve had it bumped all the way up to 20. This was
the reason the unicode-random benchmark ran so much slower (i.e. cache
contention).

Looking at emoji’s, there are a couple that need 6 code points,
and *three* that needs 7.

Now, with the limit at 7 chars, and the new ‘width’ member, the
composed struct is 8 bytes larger than before.
2021-06-24 17:30:47 +02:00
Daniel Eklöf
f865612667
vt: utf8-print: check base character before count when looking for existing compose chain
Count is more likely to be the same for many chains. Thus we’re likely
to fail sooner by checking the base character first.
2021-06-24 17:30:47 +02:00
Daniel Eklöf
51295cd7a2
render: we’ve already assigned ‘base’ a couple of lines higher up 2021-06-24 17:30:46 +02:00
Daniel Eklöf
57e636dd8e
vt: don’t call wcwidth() on all combining characters every time we add
We already have all the widths needed to calculate the new one; it’s
the base characters width (base_width), or the previous combining
chain’s width (composed->width) plus the new characters’s
width (width).
2021-06-24 17:30:46 +02:00
Daniel Eklöf
09431dd15c
vt: presentation selectors may be anywhere in the cluster 2021-06-24 17:30:46 +02:00
Daniel Eklöf
96ff29bbd3
render: repair parenthesis after rebase 2021-06-24 17:30:46 +02:00
Daniel Eklöf
b471fe31b1
render: ensure ‘cell_cols’ have been initialized 2021-06-24 17:30:46 +02:00
Daniel Eklöf
50be924285
render: handle fcft_glyph_rasterize() failure correctly 2021-06-24 17:30:46 +02:00