For performance reasons, we track whether a cell is selected or not
using a bit in a cell's attributes.
This makes it easy for the renderer to determine if the cells should
be rendered as selected or not - it just have to look at the
'selected' bit instead of doing a complex range check against the
current selection.
This works nicely in most cases. But, if the cell is updated, the
'selected' bit is cleared. This results in the renderer rendering the
cell normally, i.e. _not_ selected.
Checking for this, and re-setting the 'selected' bit when the cell is
updated (printed to) is way too expensive as it is in the hot path.
Instead, sync the 'selected' bits just before rendering. This isn't so
bad as it may sound; if there is no selection this is a no-op. Even if
there is a selection, only those cells whose 'selected' bit have been
cleared are dirtied (and thus re-rendered) - these cells would have
been re-rendered anyway.
We normally don't clear the selection when scrolling. The exception is
when the selection covers re-used rows. I.e. rows that we scroll in
and clear.
In this case we cancel the selection (we _could_ modify it and keep as
much as possible and only remove the re-used rows...). We must do
this *before* scrolling, since scrolling will swap rows (when there's
a scrolling region). When this happens, the selection is "corrupted",
and canceling it afterwards will not work.
When the client is capturing the mouse, selection can only be done by
holding done shift.
This is why a lot of selection functions are no-ops if selection isn't
currently enabled.
However, there are many cases where we actually need to modify the
selection. In particular, selection_cancel().
Thus, only check for enabled selection when we're dealing with user
input.
Bonus: this also fixes a bug where an ongoing selection were finalized
as soon as the user released shift, even if he was still holding down
the mouse button.
This ensures we _always_ commit a **new** buffer in response to a
configured event.
This fixes an issue in Gnome where e.g. tiling the window (on the
left/right side) only worked if that caused the windows size to
change.
Since the pre-composing functionality is now part of fcft, it makes
little sense to have a compile time option - there's no size benefit
to be had.
Furthermore, virtually all terminal emulators do
pre-composing (alacritty being an exception), this really isn't that
controversial.
This allows us more options when determining whether to use a
pre-composed character or not:
We now only use the pre-composed character if it's from the primary
font, or if at least one of the base or combining characters are from
a fallback font.
I.e. use glyphs from the primary font if possible. But, if one or more
of the decomposed glyphs are from a fallback font, use the
pre-composed character anyway.
This means command line parsing stops when it encounters the first
nonoption argument.
The result is that one no longer need to use '--' to ensure arguments
are passed to the shell/command, instead of parsed by foot.
That is, instead of
foot -- sh -c true
one can now do
foot sh -c true
Arguments to foot *must* go before the command:
foot --fullscreen sh -c true
We currently store up to 5 combining characters in any given
base+combining chain.
This adds a check for when that limit is about to be exceeded. When
this happens, we log the chain + the new combining character.
Since things will break anyway, we simply overwrite the last combining
character.
Instead of storing combining data per cell, realize that most
combinations are re-occurring and that there's lots of available space
left in the unicode range, and store seen base+combining combinations
chains in a per-terminal array.
When we encounter a combining character, we first try to pre-compose,
like before. If that fails, we then search for the current
base+combining combo in the list of previously seen combinations. If
not found there either, we allocate a new combo and add it to the
list. Regardless, the result is an index into this array. We store
this index, offsetted by COMB_CHARS_LO=0x40000000ul in the cell.
When rendering, we need to check if the cell character is a plain
character, or if it's a composed character (identified by checking if
the cell character is >= COMB_CHARS_LO).
Then we render the grapheme pretty much like before.