This function unmaps the terminal window, removes itself from the
wayland list of terminals and then finally destroys itself.
We ensure we don't get any callbacks/events referring to a free:d
terminal struct, we close all terminal related FDs and unmap the
wayland window.
Then, to be really really sure there aren't any (by the FDM) queued up
events, we delay the self-destruction to the next FDM poll iteration,
by opening an event FD and adding it to the FDM.
The callback for the event FD removes the FD from the FDM again, and
closes it. And then proceeds to destroy the terminal.
Since we now initialize the worker threads from term_init(), which
returns before the threads terminate, we can no longer use
stack-allocated worker contexts.
We _could_ put them in the terminal struct. But a simpler solution is
to allocate them in term_init(), and let the threads free them when
they don't need them anymore.
We do however need access to it, so provide a pointer. The difference
is that now we can have a *single* wayland instance, but multiple
terminal instances.
With this assumption, we can replace 'a % b' with 'a & (b - 1)'. In
terms of instructions, this means a fast 'and' instead of a slow
'div'.
Further optimize scrolling by:
* not double-initializing empty rows. Previously, grid_row_alloc()
called calloc(), which was then followed by a memset() when
scrolling. This is of course unnecessary.
* Don't loop the entire set of visible rows (this was done to ensure
all visible rows had been allocated, and to prefetch the cell
contents).
This isn't necessary; only newly pulled in rows can be NULL. For
now, don't prefetch at all.
That is, remove the 'regular' and 'bright' color arrays. This is
possible since the 256-color array is defined such that the first 16
colors map to the regular and bright colors.
If we scroll enough, we'll eventually end up wrapping around the
entire scrollback buffer. At this point, a selection is no longer
valid, so cancel it.
Note: this was very obvious when scrolling in the alt screen, since
its scrollback buffer is what you see on the screen (i.e. it has no
scrollback).
The 'attributes' struct is now 8 bytes and naturally packed (used to
be 9 bytes, artificially packed).
'cell' struct is now 12 bytes, naturally packed (used to be 13 bytes,
artificially packed).
Furthermore, the glyph is stored as a wchar instead of a char*. This
makes it easier (faster) to do glyph lookup when rendering.
This patch takes a bit from the foreground color value in a
cell (todo: split up foreground/background into bitfields with a
separate field for 'foreground/background' has been set), and only
re-renders cells that aren't marked as clean.
Note: we use a 'clean' bit rather than a 'dirty' bit to make it easy
to erase cells - we can (keep doing) do that by simply memsetting a
cell range to 0.
Since newly scrolled in lines will be erased, we want them in the
cache.
So, allocate and prefetch new lines, then repair non-scrolling
regions (to give the prefetch time to actually fetch the
data). Finally, erase the newly scrolled in lines.
This also fixes a bug where the fixup for the non-scrolling regions
could crash on an unallocated row (we were accessing rows that would
be, but hadn't yet been, scrolled in).
The row array may now contain NULL pointers. This means the
corresponding row hasn't yet been allocated and initialized.
On a resize, we explicitly allocate the visible rows.
Uninitialized rows are then allocated the first time they are
referenced.
linefeed moves cursor down one row (columns stays the same), or, if
the cursor is at the last row, scrolls up one row.
reverse_index does the opposite; it moves the cursor *up* one row, or,
if the cursor is at the top row, scrolls *down* one row.
Can scroll up and down, and stops when the beginning/end of history is
reached.
However, it probably breaks when the entire scrollback buffer has been
filled - we need to detect when the view has wrapped around to the
current terminal offset.
The detection of when we've reached the bottom of the history is also
flawed, and only works when we overshoot the bottom with at least a
page.
Resizing the windows while in a view most likely doesn't work.
The view will not detect a wrapped around scrollback buffer. I.e. if
the user has scrolled back, and is stationary at a view, but there is
still output being produced. Then eventually the scrollback buffer
will wrap around. In this case, the correct thing to do is make the
view start following the beginning of the history. Right now it
doesn't, meaning once the scrollback buffer wraps around, you'll start
seeing command output...