The grid is now represented with an array of row *pointers*. Each row
contains an array of cells (the row's columns).
The main point of having row pointers is we can now move rows around
almost for free.
This is useful when scrolling with scroll margins for example, where
we previously had to copy the lines in the margins. Now it's just a
matter of swapping two pointers.
This optimizes the normal scrolling case; updates are done at the
bottom of the screen and then scrolled up.
In this case, the damage list will be a more or less sorted list of
updates, oldest first.
If we're scrolling a lot, the oldest updates will eventually scroll
off screen. In this case, there's no need to keep them in the damage
list.
So, when scrolling, loop the damage list and adjust/remove updates
that have scrolled off screen (either partially, or completely).
Stop looping as soon as we see an update that has *not* scrolled off
screen.
Note that this means there may be update items in the damage list
that *has* scrolled off screen. This is especially true for random
screen writes (i.e. typical to some synthetic benchmarks).
This adds a pointer to the first cell on the current line. This
pointer must be updated every time the row changes.
The advantage is mainly that PRINT doesn't have to call
grid_get_range(), which is fairly expensive.
Since horizontal cursor movement is clamped to the current line, we
can calculate the new linear cursor without any expensive
multiplications and/or divisions.