2019-06-17 19:33:10 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
2019-07-01 12:23:38 +02:00
|
|
|
#include <stddef.h>
|
2021-01-16 20:16:00 +00:00
|
|
|
#include "debug.h"
|
2019-06-17 19:33:10 +02:00
|
|
|
#include "terminal.h"
|
2019-07-01 12:23:38 +02:00
|
|
|
|
2021-02-22 10:20:52 +01:00
|
|
|
void grid_free(struct grid *grid);
|
|
|
|
|
|
2020-05-16 23:43:05 +02:00
|
|
|
void grid_swap_row(struct grid *grid, int row_a, int row_b);
|
2019-08-22 17:33:23 +02:00
|
|
|
struct row *grid_row_alloc(int cols, bool initialize);
|
2019-07-10 16:27:55 +02:00
|
|
|
void grid_row_free(struct row *row);
|
resize: don’t reflow text on alt screen
Alt screen applications normally reflow/readjust themselves on a
window resize.
When we do it too, the result is graphical glitches/flashes since our
re-flowed text is rendered in one frame, and the application re-flowed
text soon thereafter.
We can’t avoid rendering some kind of re-flowed frame, since we don’t
know when, or even if, the application will update itself. To avoid
glitches, we need to render, as closely as possible, what the
application itself will render shortly.
This is actually pretty simple; we just need to copy the visible
content over from the old grid to the new grid. We don’t bother with
text re-flow, but simply truncate long lines.
To simplify things, we simply cancel any active selection (since often
times, it will be corrupted anyway when the application redraws
itself).
Since we’re not reflowing text, there’s no need to translate e.g. the
cursor position - we just keep the current position (but bounded to
the new dimensions).
Fun thing: ‘less’ gets corrupted if we don’t leave the cursor at
the (new) bottom row. To handle this, we check if the cursor (before
resize) is at the bottom row, and if so, we move it to the new bottom
row.
Closes #221
2020-11-24 19:00:57 +01:00
|
|
|
|
|
|
|
|
void grid_resize_without_reflow(
|
|
|
|
|
struct grid *grid, int new_rows, int new_cols,
|
|
|
|
|
int old_screen_rows, int new_screen_rows);
|
|
|
|
|
|
|
|
|
|
void grid_resize_and_reflow(
|
2020-02-15 22:19:08 +01:00
|
|
|
struct grid *grid, int new_rows, int new_cols,
|
2020-04-17 21:04:32 +02:00
|
|
|
int old_screen_rows, int new_screen_rows,
|
|
|
|
|
size_t tracking_points_count,
|
resize: don’t reflow text on alt screen
Alt screen applications normally reflow/readjust themselves on a
window resize.
When we do it too, the result is graphical glitches/flashes since our
re-flowed text is rendered in one frame, and the application re-flowed
text soon thereafter.
We can’t avoid rendering some kind of re-flowed frame, since we don’t
know when, or even if, the application will update itself. To avoid
glitches, we need to render, as closely as possible, what the
application itself will render shortly.
This is actually pretty simple; we just need to copy the visible
content over from the old grid to the new grid. We don’t bother with
text re-flow, but simply truncate long lines.
To simplify things, we simply cancel any active selection (since often
times, it will be corrupted anyway when the application redraws
itself).
Since we’re not reflowing text, there’s no need to translate e.g. the
cursor position - we just keep the current position (but bounded to
the new dimensions).
Fun thing: ‘less’ gets corrupted if we don’t leave the cursor at
the (new) bottom row. To handle this, we check if the cursor (before
resize) is at the bottom row, and if so, we move it to the new bottom
row.
Closes #221
2020-11-24 19:00:57 +01:00
|
|
|
struct coord *const _tracking_points[static tracking_points_count],
|
2020-09-06 19:14:46 +02:00
|
|
|
size_t compose_count,
|
|
|
|
|
const struct composed composed[static compose_count]);
|
2019-07-10 16:27:55 +02:00
|
|
|
|
2019-08-27 19:33:19 +02:00
|
|
|
static inline int
|
|
|
|
|
grid_row_absolute(const struct grid *grid, int row_no)
|
|
|
|
|
{
|
|
|
|
|
return (grid->offset + row_no) & (grid->num_rows - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
|
grid_row_absolute_in_view(const struct grid *grid, int row_no)
|
|
|
|
|
{
|
|
|
|
|
return (grid->view + row_no) & (grid->num_rows - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-08 13:57:31 +02:00
|
|
|
static inline struct row *
|
2019-08-22 17:33:23 +02:00
|
|
|
_grid_row_maybe_alloc(struct grid *grid, int row_no, bool alloc_if_null)
|
2019-07-08 13:57:31 +02:00
|
|
|
{
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(grid->offset >= 0);
|
2019-07-10 16:27:55 +02:00
|
|
|
|
2019-08-27 19:33:19 +02:00
|
|
|
int real_row = grid_row_absolute(grid, row_no);
|
2019-07-10 16:27:55 +02:00
|
|
|
struct row *row = grid->rows[real_row];
|
|
|
|
|
|
2019-08-22 17:33:23 +02:00
|
|
|
if (row == NULL && alloc_if_null) {
|
|
|
|
|
row = grid_row_alloc(grid->num_cols, false);
|
2019-07-10 16:27:55 +02:00
|
|
|
grid->rows[real_row] = row;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(row != NULL);
|
2019-07-10 16:27:55 +02:00
|
|
|
return row;
|
2019-07-08 13:57:31 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 17:33:23 +02:00
|
|
|
static inline struct row *
|
|
|
|
|
grid_row(struct grid *grid, int row_no)
|
|
|
|
|
{
|
|
|
|
|
return _grid_row_maybe_alloc(grid, row_no, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct row *
|
|
|
|
|
grid_row_and_alloc(struct grid *grid, int row_no)
|
|
|
|
|
{
|
|
|
|
|
return _grid_row_maybe_alloc(grid, row_no, true);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-09 16:26:36 +02:00
|
|
|
static inline struct row *
|
2019-07-10 16:27:55 +02:00
|
|
|
grid_row_in_view(struct grid *grid, int row_no)
|
2019-07-09 16:26:36 +02:00
|
|
|
{
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(grid->view >= 0);
|
2019-07-09 16:26:36 +02:00
|
|
|
|
2019-08-27 19:33:19 +02:00
|
|
|
int real_row = grid_row_absolute_in_view(grid, row_no);
|
2019-07-10 16:27:55 +02:00
|
|
|
struct row *row = grid->rows[real_row];
|
|
|
|
|
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(row != NULL);
|
2019-07-10 16:27:55 +02:00
|
|
|
return row;
|
|
|
|
|
}
|
2021-02-14 20:32:38 +01:00
|
|
|
|
2021-02-14 20:50:33 +01:00
|
|
|
void grid_row_add_uri_range(struct row *row, struct row_uri_range range);
|
|
|
|
|
|
2021-02-14 20:32:38 +01:00
|
|
|
static inline void
|
|
|
|
|
grid_row_reset_extra(struct row *row)
|
|
|
|
|
{
|
|
|
|
|
if (likely(row->extra == NULL))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
tll_foreach(row->extra->uri_ranges, it) {
|
|
|
|
|
free(it->item.uri);
|
|
|
|
|
tll_remove(row->extra->uri_ranges, it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(row->extra);
|
|
|
|
|
row->extra = NULL;
|
|
|
|
|
}
|