mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 13:37:12 +00:00
Make positions hidden by overlays range-based rather than character-based,
from Anindya Mukherjee.
This commit is contained in:
131
tty.c
131
tty.c
@ -71,6 +71,8 @@ static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
|
||||
static void tty_default_attributes(struct tty *, const struct grid_cell *,
|
||||
struct colour_palette *, u_int);
|
||||
static int tty_check_overlay(struct tty *, u_int, u_int);
|
||||
static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
|
||||
struct overlay_ranges *);
|
||||
|
||||
#define tty_use_margin(tty) \
|
||||
(tty->term->flags & TERM_DECSLRM)
|
||||
@ -1046,8 +1048,9 @@ static void
|
||||
tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
||||
u_int px, u_int nx, u_int bg)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
u_int i;
|
||||
struct client *c = tty->client;
|
||||
struct overlay_ranges r;
|
||||
u_int i;
|
||||
|
||||
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
|
||||
|
||||
@ -1083,18 +1086,13 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
||||
* Couldn't use an escape sequence, use spaces. Clear only the visible
|
||||
* bit if there is an overlay.
|
||||
*/
|
||||
for (i = 0; i < nx; i++) {
|
||||
if (!tty_check_overlay(tty, px + i, py))
|
||||
break;
|
||||
tty_check_overlay_range(tty, px, py, nx, &r);
|
||||
for (i = 0; i < OVERLAY_MAX_RANGES; i++) {
|
||||
if (r.nx[i] == 0)
|
||||
continue;
|
||||
tty_cursor(tty, r.px[i], py);
|
||||
tty_repeat_space(tty, r.nx[i]);
|
||||
}
|
||||
tty_cursor(tty, px, py);
|
||||
tty_repeat_space(tty, i);
|
||||
for (; i < nx; i++) {
|
||||
if (tty_check_overlay(tty, px + i, py))
|
||||
break;
|
||||
}
|
||||
tty_cursor(tty, px + i, py);
|
||||
tty_repeat_space(tty, nx - i);
|
||||
}
|
||||
|
||||
/* Clear a line, adjusting to visible part of pane. */
|
||||
@ -1306,14 +1304,44 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
|
||||
return (&new);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a single character is obstructed by the overlay and return a
|
||||
* boolean.
|
||||
*/
|
||||
static int
|
||||
tty_check_overlay(struct tty *tty, u_int px, u_int py)
|
||||
{
|
||||
struct overlay_ranges r;
|
||||
|
||||
/*
|
||||
* A unit width range will always return nx[2] == 0 from a check, even
|
||||
* with multiple overlays, so it's sufficient to check just the first
|
||||
* two entries.
|
||||
*/
|
||||
tty_check_overlay_range(tty, px, py, 1, &r);
|
||||
if (r.nx[0] + r.nx[1] == 0)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Return parts of the input range which are visible. */
|
||||
static void
|
||||
tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx,
|
||||
struct overlay_ranges *r)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
|
||||
if (c->overlay_check == NULL)
|
||||
return (1);
|
||||
return (c->overlay_check(c, c->overlay_data, px, py));
|
||||
if (c->overlay_check == NULL) {
|
||||
r->px[0] = px;
|
||||
r->nx[0] = nx;
|
||||
r->px[1] = 0;
|
||||
r->nx[1] = 0;
|
||||
r->px[2] = 0;
|
||||
r->nx[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
c->overlay_check(c, c->overlay_data, px, py, nx, r);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1326,11 +1354,12 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
const struct grid_cell *gcp;
|
||||
struct grid_line *gl;
|
||||
struct client *c = tty->client;
|
||||
u_int i, j, ux, sx, width, hidden;
|
||||
struct overlay_ranges r;
|
||||
u_int i, j, ux, sx, width, hidden, eux, nxx;
|
||||
u_int cellsize;
|
||||
int flags, cleared = 0, wrapped = 0;
|
||||
char buf[512];
|
||||
size_t len;
|
||||
u_int cellsize;
|
||||
|
||||
log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__,
|
||||
px, py, nx, atx, aty);
|
||||
@ -1430,29 +1459,31 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
else
|
||||
memcpy(&last, gcp, sizeof last);
|
||||
|
||||
tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width,
|
||||
&r);
|
||||
hidden = 0;
|
||||
for (j = 0; j < gcp->data.width; j++) {
|
||||
if (!tty_check_overlay(tty, atx + ux + j, aty))
|
||||
hidden++;
|
||||
}
|
||||
for (j = 0; j < OVERLAY_MAX_RANGES; j++)
|
||||
hidden += r.nx[j];
|
||||
hidden = gcp->data.width - hidden;
|
||||
if (hidden != 0 && hidden == gcp->data.width) {
|
||||
if (~gcp->flags & GRID_FLAG_PADDING)
|
||||
ux += gcp->data.width;
|
||||
} else if (hidden != 0 || ux + gcp->data.width > nx) {
|
||||
if (~gcp->flags & GRID_FLAG_PADDING) {
|
||||
tty_attributes(tty, &last, defaults, palette);
|
||||
tty_cursor(tty, atx + ux, aty);
|
||||
for (j = 0; j < gcp->data.width; j++) {
|
||||
if (ux > nx)
|
||||
break;
|
||||
if (tty_check_overlay(tty, atx + ux,
|
||||
aty))
|
||||
tty_putc(tty, ' ');
|
||||
else {
|
||||
tty_cursor(tty, atx + ux + 1,
|
||||
aty);
|
||||
for (j = 0; j < OVERLAY_MAX_RANGES; j++) {
|
||||
if (r.nx[j] == 0)
|
||||
continue;
|
||||
/* Effective width drawn so far. */
|
||||
eux = r.px[j] - atx;
|
||||
if (eux < nx) {
|
||||
tty_cursor(tty, r.px[j], aty);
|
||||
nxx = nx - eux;
|
||||
if (r.nx[j] > nxx)
|
||||
r.nx[j] = nxx;
|
||||
tty_repeat_space(tty, r.nx[j]);
|
||||
ux = eux + r.nx[j];
|
||||
}
|
||||
ux++;
|
||||
}
|
||||
}
|
||||
} else if (gcp->attr & GRID_ATTR_CHARSET) {
|
||||
@ -1926,7 +1957,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
const struct grid_cell *gcp = ctx->cell;
|
||||
struct screen *s = ctx->s;
|
||||
u_int i, px, py;
|
||||
struct overlay_ranges r;
|
||||
u_int px, py, i, vis = 0;
|
||||
|
||||
px = ctx->xoff + ctx->ocx - ctx->wox;
|
||||
py = ctx->yoff + ctx->ocy - ctx->woy;
|
||||
@ -1936,13 +1968,14 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
|
||||
/* Handle partially obstructed wide characters. */
|
||||
if (gcp->data.width > 1) {
|
||||
for (i = 0; i < gcp->data.width; i++) {
|
||||
if (!tty_check_overlay(tty, px + i, py)) {
|
||||
tty_draw_line(tty, s, s->cx, s->cy,
|
||||
tty_check_overlay_range(tty, px, py, gcp->data.width, &r);
|
||||
for (i = 0; i < OVERLAY_MAX_RANGES; i++)
|
||||
vis += r.nx[i];
|
||||
if (vis < gcp->data.width) {
|
||||
tty_draw_line(tty, s, s->cx, s->cy,
|
||||
gcp->data.width, px, py, &ctx->defaults,
|
||||
ctx->palette);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1960,7 +1993,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
void
|
||||
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
u_int i, hide = 0;
|
||||
struct overlay_ranges r;
|
||||
u_int i, px;
|
||||
|
||||
if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1))
|
||||
return;
|
||||
@ -1985,18 +2019,15 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
|
||||
tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette);
|
||||
for (i = 0; i < ctx->num; i++) {
|
||||
if (!tty_check_overlay(tty, tty->cx + i, tty->cy))
|
||||
break;
|
||||
px = tty->cx;
|
||||
tty_check_overlay_range(tty, px, tty->cy, ctx->num, &r);
|
||||
for (i = 0; i < OVERLAY_MAX_RANGES; i++) {
|
||||
if (r.nx[i] == 0)
|
||||
continue;
|
||||
tty_cursor(tty, r.px[i], tty->cy);
|
||||
tty_putn(tty, (char *)ctx->ptr + r.px[i] - px, r.nx[i],
|
||||
r.nx[i]);
|
||||
}
|
||||
tty_putn(tty, ctx->ptr, i, i);
|
||||
for (; i < ctx->num; i++) {
|
||||
if (tty_check_overlay(tty, tty->cx + hide, tty->cy))
|
||||
break;
|
||||
hide++;
|
||||
}
|
||||
tty_cursor(tty, tty->cx + hide, tty->cy);
|
||||
tty_putn(tty, (char *)ctx->ptr + i, ctx->num - i, ctx->num - i);
|
||||
}
|
||||
|
||||
void
|
||||
|
Reference in New Issue
Block a user