mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
grid: reflow: handle styled underlines
This commit is contained in:
parent
8e2402605e
commit
b20302c2a7
1 changed files with 128 additions and 38 deletions
166
grid.c
166
grid.c
|
|
@ -238,6 +238,18 @@ uri_range_append(struct row_data *extra, int start, int end, uint64_t id,
|
||||||
uri_range_append_no_strdup(extra, start, end, id, xstrdup(uri));
|
uri_range_append_no_strdup(extra, start, end, id, xstrdup(uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
curly_range_append(struct row_data *extra, int start, int end,
|
||||||
|
struct curly_range_data data)
|
||||||
|
{
|
||||||
|
range_ensure_size(&extra->curly_ranges, 1);
|
||||||
|
extra->curly_ranges.v[extra->curly_ranges.count++] = (struct row_range){
|
||||||
|
.start = start,
|
||||||
|
.end = end,
|
||||||
|
.curly = data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
range_delete(struct row_ranges *ranges, enum row_range_type type, size_t idx)
|
range_delete(struct row_ranges *ranges, enum row_range_type type, size_t idx)
|
||||||
{
|
{
|
||||||
|
|
@ -303,8 +315,8 @@ grid_snapshot(const struct grid *grid)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < extra->curly_ranges.count; i++) {
|
for (int i = 0; i < extra->curly_ranges.count; i++) {
|
||||||
//const struct row_range *range = &extra->curly_ranges.v[i];
|
const struct row_range *range = &extra->curly_ranges.v[i];
|
||||||
BUG("TODO");
|
curly_range_append(clone_extra, range->start, range->end, range->curly);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
clone_row->extra = NULL;
|
clone_row->extra = NULL;
|
||||||
|
|
@ -535,18 +547,17 @@ grid_resize_without_reflow(
|
||||||
uri_range_append(new_extra, start, end, range->uri.id, range->uri.uri);
|
uri_range_append(new_extra, start, end, range->uri.id, range->uri.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < old_extra->uri_ranges.count; i++) {
|
for (int i = 0; i < old_extra->curly_ranges.count; i++) {
|
||||||
const struct row_range *range = &old_extra->uri_ranges.v[i];
|
const struct row_range *range = &old_extra->curly_ranges.v[i];
|
||||||
|
|
||||||
if (range->start >= new_cols) {
|
if (range->start >= new_cols) {
|
||||||
/* The whole range is truncated */
|
/* The whole range is truncated */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//const int start = range->start;
|
const int start = range->start;
|
||||||
//const int end = min(range->end, new_cols - 1);
|
const int end = min(range->end, new_cols - 1);
|
||||||
//uri_range_append(new_extra, start, end, range->uri.id, range->uri.uri);
|
curly_range_append(new_extra, start, end, range->curly);
|
||||||
BUG("TODO");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,8 +634,8 @@ reflow_uri_range_start(struct row_range *range, struct row *new_row,
|
||||||
int new_col_idx)
|
int new_col_idx)
|
||||||
{
|
{
|
||||||
ensure_row_has_extra_data(new_row);
|
ensure_row_has_extra_data(new_row);
|
||||||
uri_range_append_no_strdup
|
uri_range_append_no_strdup(
|
||||||
(new_row->extra, new_col_idx, -1, range->uri.id, range->uri.uri);
|
new_row->extra, new_col_idx, -1, range->uri.id, range->uri.uri);
|
||||||
range->uri.uri = NULL;
|
range->uri.uri = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -643,6 +654,33 @@ reflow_uri_range_end(struct row_range *range, struct row *new_row,
|
||||||
new_range->end = new_col_idx;
|
new_range->end = new_col_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reflow_curly_range_start(struct row_range *range, struct row *new_row,
|
||||||
|
int new_col_idx)
|
||||||
|
{
|
||||||
|
ensure_row_has_extra_data(new_row);
|
||||||
|
curly_range_append(new_row->extra, new_col_idx, -1, range->curly);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
reflow_curly_range_end(struct row_range *range, struct row *new_row,
|
||||||
|
int new_col_idx)
|
||||||
|
{
|
||||||
|
struct row_data *extra = new_row->extra;
|
||||||
|
xassert(extra->curly_ranges.count > 0);
|
||||||
|
|
||||||
|
struct row_range *new_range =
|
||||||
|
&extra->curly_ranges.v[extra->curly_ranges.count - 1];
|
||||||
|
|
||||||
|
xassert(new_range->curly.style == range->curly.style);
|
||||||
|
xassert(new_range->curly.color_src == range->curly.color_src);
|
||||||
|
xassert(new_range->curly.color == range->curly.color);
|
||||||
|
|
||||||
|
xassert(new_range->end < 0);
|
||||||
|
new_range->end = new_col_idx;
|
||||||
|
}
|
||||||
|
|
||||||
static struct row *
|
static struct row *
|
||||||
_line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row,
|
_line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row,
|
||||||
int *row_idx, int *col_idx, int row_count, int col_count)
|
int *row_idx, int *col_idx, int row_count, int col_count)
|
||||||
|
|
@ -703,6 +741,21 @@ _line_wrap(struct grid *old_grid, struct row **new_grid, struct row *row,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extra->curly_ranges.count > 0) {
|
||||||
|
struct row_range *range =
|
||||||
|
&extra->curly_ranges.v[extra->curly_ranges.count - 1];
|
||||||
|
|
||||||
|
if (range->end < 0) {
|
||||||
|
|
||||||
|
/* Terminate URI range on the previous row */
|
||||||
|
range->end = col_count - 1;
|
||||||
|
|
||||||
|
/* Open a new range on the new/current row */
|
||||||
|
ensure_row_has_extra_data(new_row);
|
||||||
|
curly_range_append(new_row->extra, 0, -1, range->curly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new_row;
|
return new_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -887,12 +940,13 @@ grid_resize_and_reflow(
|
||||||
tp = NULL;
|
tp = NULL;
|
||||||
|
|
||||||
/* Does this row have any URIs? */
|
/* Does this row have any URIs? */
|
||||||
struct row_range *range, *range_terminator;
|
struct row_range *uri_range, *uri_range_terminator;
|
||||||
|
struct row_range *curly_range, *curly_range_terminator;
|
||||||
struct row_data *extra = old_row->extra;
|
struct row_data *extra = old_row->extra;
|
||||||
|
|
||||||
if (extra != NULL && extra->uri_ranges.count > 0) {
|
if (extra != NULL && extra->uri_ranges.count > 0) {
|
||||||
range = &extra->uri_ranges.v[0];
|
uri_range = &extra->uri_ranges.v[0];
|
||||||
range_terminator = &extra->uri_ranges.v[extra->uri_ranges.count];
|
uri_range_terminator = &extra->uri_ranges.v[extra->uri_ranges.count];
|
||||||
|
|
||||||
/* Make sure the *last* URI range's end point is included
|
/* Make sure the *last* URI range's end point is included
|
||||||
* in the copy */
|
* in the copy */
|
||||||
|
|
@ -900,18 +954,32 @@ grid_resize_and_reflow(
|
||||||
&extra->uri_ranges.v[extra->uri_ranges.count - 1];
|
&extra->uri_ranges.v[extra->uri_ranges.count - 1];
|
||||||
col_count = max(col_count, last_on_row->end + 1);
|
col_count = max(col_count, last_on_row->end + 1);
|
||||||
} else
|
} else
|
||||||
range = range_terminator = NULL;
|
uri_range = uri_range_terminator = NULL;
|
||||||
|
|
||||||
|
if (extra != NULL && extra->curly_ranges.count > 0) {
|
||||||
|
curly_range = &extra->curly_ranges.v[0];
|
||||||
|
curly_range_terminator = &extra->curly_ranges.v[extra->curly_ranges.count];
|
||||||
|
|
||||||
|
const struct row_range *last_on_row =
|
||||||
|
&extra->curly_ranges.v[extra->curly_ranges.count - 1];
|
||||||
|
col_count = max(col_count, last_on_row->end + 1);
|
||||||
|
} else
|
||||||
|
curly_range = curly_range_terminator = NULL;
|
||||||
|
|
||||||
for (int start = 0, left = col_count; left > 0;) {
|
for (int start = 0, left = col_count; left > 0;) {
|
||||||
int end;
|
int end;
|
||||||
bool tp_break = false;
|
bool tp_break = false;
|
||||||
bool uri_break = false;
|
bool uri_break = false;
|
||||||
|
bool curly_break = false;
|
||||||
bool ftcs_break = false;
|
bool ftcs_break = false;
|
||||||
|
|
||||||
/* Figure out where to end this chunk */
|
/* Figure out where to end this chunk */
|
||||||
{
|
{
|
||||||
const int uri_col = range != range_terminator
|
const int uri_col = uri_range != uri_range_terminator
|
||||||
? ((range->start >= start ? range->start : range->end) + 1)
|
? ((uri_range->start >= start ? uri_range->start : uri_range->end) + 1)
|
||||||
|
: INT_MAX;
|
||||||
|
const int curly_col = curly_range != curly_range_terminator
|
||||||
|
? ((curly_range->start >= start ? curly_range->start : curly_range->end) + 1)
|
||||||
: INT_MAX;
|
: INT_MAX;
|
||||||
const int tp_col = tp != NULL ? tp->col + 1 : INT_MAX;
|
const int tp_col = tp != NULL ? tp->col + 1 : INT_MAX;
|
||||||
const int ftcs_col = old_row->shell_integration.cmd_start >= start
|
const int ftcs_col = old_row->shell_integration.cmd_start >= start
|
||||||
|
|
@ -920,9 +988,10 @@ grid_resize_and_reflow(
|
||||||
? old_row->shell_integration.cmd_end + 1
|
? old_row->shell_integration.cmd_end + 1
|
||||||
: INT_MAX;
|
: INT_MAX;
|
||||||
|
|
||||||
end = min(col_count, min(min(tp_col, uri_col), ftcs_col));
|
end = min(col_count, min(min(tp_col, min(uri_col, curly_col)), ftcs_col));
|
||||||
|
|
||||||
uri_break = end == uri_col;
|
uri_break = end == uri_col;
|
||||||
|
curly_break = end == curly_col;
|
||||||
tp_break = end == tp_col;
|
tp_break = end == tp_col;
|
||||||
ftcs_break = end == ftcs_col;
|
ftcs_break = end == ftcs_col;
|
||||||
}
|
}
|
||||||
|
|
@ -1033,15 +1102,28 @@ grid_resize_and_reflow(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uri_break) {
|
if (uri_break) {
|
||||||
xassert(range != NULL);
|
xassert(uri_range != NULL);
|
||||||
|
|
||||||
if (range->start == end - 1)
|
if (uri_range->start == end - 1)
|
||||||
reflow_uri_range_start(range, new_row, new_col_idx - 1);
|
reflow_uri_range_start(uri_range, new_row, new_col_idx - 1);
|
||||||
|
|
||||||
if (range->end == end - 1) {
|
if (uri_range->end == end - 1) {
|
||||||
reflow_uri_range_end(range, new_row, new_col_idx - 1);
|
reflow_uri_range_end(uri_range, new_row, new_col_idx - 1);
|
||||||
grid_row_uri_range_destroy(range);
|
grid_row_uri_range_destroy(uri_range);
|
||||||
range++;
|
uri_range++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curly_break) {
|
||||||
|
xassert(curly_range != NULL);
|
||||||
|
|
||||||
|
if (curly_range->start == end - 1)
|
||||||
|
reflow_curly_range_start(curly_range, new_row, new_col_idx - 1);
|
||||||
|
|
||||||
|
if (curly_range->end == end - 1) {
|
||||||
|
reflow_curly_range_end(curly_range, new_row, new_col_idx - 1);
|
||||||
|
grid_row_curly_range_destroy(curly_range);
|
||||||
|
curly_range++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1067,20 +1149,26 @@ grid_resize_and_reflow(
|
||||||
|
|
||||||
if (r + 1 < old_rows)
|
if (r + 1 < old_rows)
|
||||||
line_wrap();
|
line_wrap();
|
||||||
else if (new_row->extra != NULL &&
|
else if (new_row->extra != NULL) {
|
||||||
new_row->extra->uri_ranges.count > 0)
|
if (new_row->extra->uri_ranges.count > 0) {
|
||||||
{
|
/*
|
||||||
/*
|
* line_wrap() "closes" still-open URIs. Since
|
||||||
* line_wrap() "closes" still-open URIs. Since this is
|
* this is the *last* row, and since we're
|
||||||
* the *last* row, and since we're line-breaking due
|
* line-breaking due to a hard line-break (rather
|
||||||
* to a hard line-break (rather than running out of
|
* than running out of cells in the "new_row"),
|
||||||
* cells in the "new_row"), there shouldn't be an open
|
* there shouldn't be an open URI (it would have
|
||||||
* URI (it would have been closed when we reached the
|
* been closed when we reached the end of the URI
|
||||||
* end of the URI while reflowing the last "old"
|
* while reflowing the last "old" row).
|
||||||
* row).
|
*/
|
||||||
*/
|
int last_idx = new_row->extra->uri_ranges.count - 1;
|
||||||
uint32_t last_idx = new_row->extra->uri_ranges.count - 1;
|
xassert(new_row->extra->uri_ranges.v[last_idx].end >= 0);
|
||||||
xassert(new_row->extra->uri_ranges.v[last_idx].end >= 0);
|
}
|
||||||
|
|
||||||
|
if (new_row->extra->curly_ranges.count > 0) {
|
||||||
|
int last_idx = new_row->extra->curly_ranges.count - 1;
|
||||||
|
xassert(new_row->extra->curly_ranges.v[last_idx].end >= 0);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1112,6 +1200,8 @@ grid_resize_and_reflow(
|
||||||
|
|
||||||
for (size_t i = 0; i < row->extra->uri_ranges.count; i++)
|
for (size_t i = 0; i < row->extra->uri_ranges.count; i++)
|
||||||
xassert(row->extra->uri_ranges.v[i].end >= 0);
|
xassert(row->extra->uri_ranges.v[i].end >= 0);
|
||||||
|
for (size_t i = 0; i < row->extra->curly_ranges.count; i++)
|
||||||
|
xassert(row->extra->curly_ranges.v[i].end >= 0);
|
||||||
|
|
||||||
verify_no_overlapping_ranges(row->extra);
|
verify_no_overlapping_ranges(row->extra);
|
||||||
verify_ranges_are_sorted(row->extra);
|
verify_ranges_are_sorted(row->extra);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue