aboutsummaryrefslogtreecommitdiff
path: root/screen-redraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'screen-redraw.c')
-rw-r--r--screen-redraw.c382
1 files changed, 231 insertions, 151 deletions
diff --git a/screen-redraw.c b/screen-redraw.c
index 931bb20f..167389b4 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -33,22 +33,15 @@ struct screen_redraw_ctx {
u_int sx;
u_int sy;
+ u_int ox;
+ u_int oy;
};
-static int screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
-static int screen_redraw_cell_border(struct client *, u_int, u_int);
-static int screen_redraw_check_cell(struct client *, u_int, u_int, int,
- struct window_pane **);
-static int screen_redraw_check_is(u_int, u_int, int, int, struct window *,
- struct window_pane *, struct window_pane *);
-
-static int screen_redraw_make_pane_status(struct client *, struct window *,
- struct window_pane *);
-static void screen_redraw_draw_pane_status(struct client *, int);
-
static void screen_redraw_draw_borders(struct screen_redraw_ctx *);
static void screen_redraw_draw_panes(struct screen_redraw_ctx *);
static void screen_redraw_draw_status(struct screen_redraw_ctx *);
+static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
+ struct window_pane *);
static void screen_redraw_draw_number(struct screen_redraw_ctx *,
struct window_pane *);
@@ -327,35 +320,67 @@ screen_redraw_make_pane_status(struct client *c, struct window *w,
/* Draw pane status. */
static void
-screen_redraw_draw_pane_status(struct client *c, int pane_status)
+screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
{
+ struct client *c = ctx->c;
struct window *w = c->session->curw->window;
- struct options *oo = c->session->options;
struct tty *tty = &c->tty;
struct window_pane *wp;
- int spos;
- u_int yoff;
+ struct screen *s;
+ u_int i, x, width, xoff, yoff, size;
+
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
- spos = options_get_number(oo, "status-position");
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp))
continue;
- if (pane_status == CELL_STATUS_TOP)
+ s = &wp->status_screen;
+
+ size = wp->status_size;
+ if (ctx->pane_status == CELL_STATUS_TOP)
yoff = wp->yoff - 1;
else
yoff = wp->yoff + wp->sy;
- if (spos == 0)
- yoff += 1;
+ xoff = wp->xoff + 2;
+
+ if (xoff + size <= ctx->ox ||
+ xoff >= ctx->ox + ctx->sx ||
+ yoff < ctx->oy ||
+ yoff >= ctx->oy + ctx->sy)
+ continue;
- tty_draw_line(tty, NULL, &wp->status_screen, 0, wp->xoff + 2,
- yoff);
+ if (xoff >= ctx->ox && xoff + size <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ i = 0;
+ x = xoff - ctx->ox;
+ width = size;
+ } else if (xoff < ctx->ox && xoff + size > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ i = ctx->ox;
+ x = 0;
+ width = ctx->sx;
+ } else if (xoff < ctx->ox) {
+ /* Left not visible. */
+ i = ctx->ox - xoff;
+ x = 0;
+ width = size - i;
+ } else {
+ /* Right not visible. */
+ i = 0;
+ x = xoff - ctx->ox;
+ width = size - x;
+ }
+
+ if (ctx->top)
+ yoff += ctx->lines;
+ tty_draw_line(tty, NULL, s, i, 0, width, x, yoff - ctx->oy);
}
tty_cursor(tty, 0, 0);
}
/* Update status line and change flags if unchanged. */
-void
-screen_redraw_update(struct client *c)
+static int
+screen_redraw_update(struct client *c, int flags)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
@@ -368,8 +393,8 @@ screen_redraw_update(struct client *c)
redraw = status_prompt_redraw(c);
else
redraw = status_redraw(c);
- if (!redraw)
- c->flags &= ~CLIENT_STATUS;
+ if (!redraw && (~flags & CLIENT_REDRAWSTATUSALWAYS))
+ flags &= ~CLIENT_REDRAWSTATUS;
if (options_get_number(wo, "pane-border-status") != CELL_STATUS_OFF) {
redraw = 0;
@@ -378,99 +403,96 @@ screen_redraw_update(struct client *c)
redraw = 1;
}
if (redraw)
- c->flags |= CLIENT_BORDERS;
+ flags |= CLIENT_REDRAWBORDERS;
}
+ return (flags);
}
-/* Redraw entire screen. */
-void
-screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
- int draw_borders)
+/* Set up redraw context. */
+static void
+screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
{
- struct options *oo = c->session->options;
- struct tty *tty = &c->tty;
- struct window *w = c->session->curw->window;
- struct options *wo = w->options;
- struct screen_redraw_ctx ctx;
-
- if (c->flags & CLIENT_SUSPENDED)
- return;
+ struct session *s = c->session;
+ struct options *oo = s->options;
+ struct window *w = s->curw->window;
+ struct options *wo = w->options;
- memset(&ctx, 0, sizeof ctx);
- ctx.c = c;
+ memset(ctx, 0, sizeof *ctx);
+ ctx->c = c;
- if (c->flags & CLIENT_STATUSOFF)
- ctx.lines = 0;
- else
- ctx.lines = status_line_size(c->session);
+ ctx->lines = status_line_size(c);
if (c->message_string != NULL || c->prompt_string != NULL)
- ctx.lines = (ctx.lines == 0) ? 1 : ctx.lines;
+ ctx->lines = (ctx->lines == 0) ? 1 : ctx->lines;
+ if (ctx->lines != 0 && options_get_number(oo, "status-position") == 0)
+ ctx->top = 1;
+ ctx->pane_status = options_get_number(wo, "pane-border-status");
+
+ tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy);
- if (ctx.lines != 0 && options_get_number(oo, "status-position") == 0)
- ctx.top = 1;
- ctx.pane_status = options_get_number(wo, "pane-border-status");
+ log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__, c->name,
+ w->id, ctx->ox, ctx->oy, ctx->sx, ctx->sy, ctx->lines, ctx->top);
+}
+
+/* Redraw entire screen. */
+void
+screen_redraw_screen(struct client *c)
+{
+ struct screen_redraw_ctx ctx;
+ int flags;
- ctx.sx = tty->sx;
- ctx.sy = tty->sy - ctx.lines;
+ if (c->flags & CLIENT_SUSPENDED)
+ return;
- if (ctx.lines == 0)
- draw_status = 0;
+ flags = screen_redraw_update(c, c->flags);
+ screen_redraw_set_context(c, &ctx);
- if (draw_borders) {
+ if (flags & (CLIENT_REDRAWWINDOW|CLIENT_REDRAWBORDERS)) {
if (ctx.pane_status != CELL_STATUS_OFF)
- screen_redraw_draw_pane_status(c, ctx.pane_status);
+ screen_redraw_draw_pane_status(&ctx);
screen_redraw_draw_borders(&ctx);
}
- if (draw_panes)
+ if (flags & CLIENT_REDRAWWINDOW)
screen_redraw_draw_panes(&ctx);
- if (draw_status)
+ if (ctx.lines != 0 &&
+ (flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS)))
screen_redraw_draw_status(&ctx);
- tty_reset(tty);
+ tty_reset(&c->tty);
}
-/* Draw a single pane. */
+/* Redraw a single pane. */
void
screen_redraw_pane(struct client *c, struct window_pane *wp)
{
- u_int i, yoff;
+ struct screen_redraw_ctx ctx;
if (!window_pane_visible(wp))
return;
- yoff = wp->yoff;
- if (status_at_line(c) == 0)
- yoff += status_line_size(c->session);
-
- log_debug("%s: redraw pane %%%u (at %u,%u)", c->name, wp->id,
- wp->xoff, yoff);
+ screen_redraw_set_context(c, &ctx);
- for (i = 0; i < wp->sy; i++)
- tty_draw_pane(&c->tty, wp, i, wp->xoff, yoff);
+ screen_redraw_draw_pane(&ctx, wp);
tty_reset(&c->tty);
}
/* Draw a border cell. */
static void
-screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int x, u_int y,
- int small, u_int msgx, u_int msgy, struct grid_cell *m_active_gc,
- struct grid_cell *active_gc, struct grid_cell *m_other_gc,
- struct grid_cell *other_gc)
+screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j,
+ struct grid_cell *m_active_gc, struct grid_cell *active_gc,
+ struct grid_cell *m_other_gc, struct grid_cell *other_gc)
{
- struct client *c = ctx->c;
- struct session *s = c->session;
- struct window *w = s->curw->window;
- struct tty *tty = &c->tty;
- struct window_pane *wp;
- struct window_pane *active = w->active;
- struct window_pane *marked = marked_pane.wp;
- u_int type;
- int flag, pane_status = ctx->pane_status;
+ struct client *c = ctx->c;
+ struct session *s = c->session;
+ struct window *w = s->curw->window;
+ struct tty *tty = &c->tty;
+ struct window_pane *wp;
+ struct window_pane *active = w->active;
+ struct window_pane *marked = marked_pane.wp;
+ u_int type, x = ctx->ox + i, y = ctx->oy + j;
+ int flag, pane_status = ctx->pane_status;
type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
if (type == CELL_INSIDE)
return;
- if (type == CELL_OUTSIDE && small && x > msgx && y == msgy)
- return;
flag = screen_redraw_check_is(x, y, type, pane_status, w, active, wp);
if (server_is_marked(s, s->curw, marked_pane.wp) &&
@@ -484,9 +506,9 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int x, u_int y,
else
tty_attributes(tty, other_gc, NULL);
if (ctx->top)
- tty_cursor(tty, x, ctx->lines + y);
+ tty_cursor(tty, i, ctx->lines + j);
else
- tty_cursor(tty, x, y);
+ tty_cursor(tty, i, j);
tty_putc(tty, CELL_BORDERS[type]);
}
@@ -497,42 +519,12 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
struct client *c = ctx->c;
struct session *s = c->session;
struct window *w = s->curw->window;
- struct options *oo = w->options;
struct tty *tty = &c->tty;
+ struct options *oo = w->options;
struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc;
- struct grid_cell msg_gc;
- u_int i, j, msgx = 0, msgy = 0;
- int small, flags;
- char msg[256];
- const char *tmp;
- size_t msglen = 0;
-
- small = (ctx->sy + ctx->top > w->sy) || (ctx->sx > w->sx);
- if (small) {
- flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
- if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT))
- tmp = "force-width, force-height";
- else if (flags == WINDOW_FORCEWIDTH)
- tmp = "force-width";
- else if (flags == WINDOW_FORCEHEIGHT)
- tmp = "force-height";
- else if (c->flags & CLIENT_STATUSOFF)
- tmp = "status line";
- else
- tmp = "a smaller client";
- xsnprintf(msg, sizeof msg, "(size %ux%u from %s)",
- w->sx, w->sy, tmp);
- msglen = strlen(msg);
-
- if (ctx->sy - 1 + ctx->top > w->sy && ctx->sx >= msglen) {
- msgx = ctx->sx - msglen;
- msgy = ctx->sy - 1 + ctx->top;
- } else if (ctx->sx - w->sx > msglen) {
- msgx = ctx->sx - msglen;
- msgy = ctx->sy - 1 + ctx->top;
- } else
- small = 0;
- }
+ u_int i, j;
+
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
style_apply(&other_gc, oo, "pane-border-style");
style_apply(&active_gc, oo, "pane-active-border-style");
@@ -543,20 +535,12 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
memcpy(&m_active_gc, &active_gc, sizeof m_active_gc);
m_active_gc.attr ^= GRID_ATTR_REVERSE;
- for (j = 0; j < ctx->sy; j++) {
- for (i = 0; i < ctx->sx; i++) {
- screen_redraw_draw_borders_cell(ctx, i, j, small,
- msgx, msgy, &m_active_gc, &active_gc, &m_other_gc,
- &other_gc);
+ for (j = 0; j < tty->sy - ctx->lines; j++) {
+ for (i = 0; i < tty->sx; i++) {
+ screen_redraw_draw_borders_cell(ctx, i, j,
+ &m_active_gc, &active_gc, &m_other_gc, &other_gc);
}
}
-
- if (small) {
- memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc);
- tty_attributes(tty, &msg_gc, NULL);
- tty_cursor(tty, msgx, msgy);
- tty_puts(tty, msg);
- }
}
/* Draw the panes. */
@@ -565,19 +549,14 @@ screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
{
struct client *c = ctx->c;
struct window *w = c->session->curw->window;
- struct tty *tty = &c->tty;
struct window_pane *wp;
- u_int i, y;
- if (ctx->top)
- y = ctx->lines;
- else
- y = 0;
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
+
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp))
continue;
- for (i = 0; i < wp->sy; i++)
- tty_draw_pane(tty, wp, i, wp->xoff, y + wp->yoff);
+ screen_redraw_draw_pane(ctx, wp);
if (c->flags & CLIENT_IDENTIFY)
screen_redraw_draw_number(ctx, wp);
}
@@ -588,15 +567,74 @@ static void
screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
{
struct client *c = ctx->c;
+ struct window *w = c->session->curw->window;
struct tty *tty = &c->tty;
+ struct screen *s = &c->status.status;
u_int i, y;
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
+
if (ctx->top)
y = 0;
else
- y = ctx->sy;
+ y = c->tty.sy - ctx->lines;
for (i = 0; i < ctx->lines; i++)
- tty_draw_line(tty, NULL, &c->status.status, i, 0, y);
+ tty_draw_line(tty, NULL, s, 0, i, UINT_MAX, 0, y + i);
+}
+
+/* Draw one pane. */
+static void
+screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
+{
+ struct client *c = ctx->c;
+ struct window *w = c->session->curw->window;
+ struct tty *tty = &c->tty;
+ struct screen *s;
+ u_int i, j, top, x, y, width;
+
+ log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id);
+
+ if (wp->xoff + wp->sx <= ctx->ox || wp->xoff >= ctx->ox + ctx->sx)
+ return;
+ if (ctx->top)
+ top = ctx->lines;
+ else
+ top = 0;
+
+ s = wp->screen;
+ for (j = 0; j < wp->sy; j++) {
+ if (wp->yoff + j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy)
+ continue;
+ y = top + wp->yoff + j - ctx->oy;
+
+ if (wp->xoff >= ctx->ox &&
+ wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ i = 0;
+ x = wp->xoff - ctx->ox;
+ width = wp->sx;
+ } else if (wp->xoff < ctx->ox &&
+ wp->xoff + wp->sx > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ i = ctx->ox;
+ x = 0;
+ width = ctx->sx;
+ } else if (wp->xoff < ctx->ox) {
+ /* Left not visible. */
+ i = ctx->ox - wp->xoff;
+ x = 0;
+ width = wp->sx - i;
+ } else {
+ /* Right not visible. */
+ i = 0;
+ x = wp->xoff - ctx->ox;
+ width = ctx->sx - x;
+ }
+ log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
+ __func__, c->name, wp->id, i, j, x, y, width);
+
+ tty_draw_line(tty, wp, s, i, j, width, x, y);
+ }
}
/* Draw number on a pane. */
@@ -609,27 +647,69 @@ screen_redraw_draw_number(struct screen_redraw_ctx *ctx, struct window_pane *wp)
struct options *oo = s->options;
struct window *w = wp->window;
struct grid_cell gc;
- u_int idx, px, py, i, j, xoff, yoff;
+ u_int idx, px, py, i, j, xoff, yoff, sx, sy;
int colour, active_colour;
char buf[16], *ptr;
size_t len;
+ if (wp->xoff + wp->sx <= ctx->ox ||
+ wp->xoff >= ctx->ox + ctx->sx ||
+ wp->yoff + wp->sy <= ctx->oy ||
+ wp->yoff >= ctx->oy + ctx->sy)
+ return;
+
+ if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ xoff = wp->xoff - ctx->ox;
+ sx = wp->sx;
+ } else if (wp->xoff < ctx->ox &&
+ wp->xoff + wp->sx > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ xoff = 0;
+ sx = ctx->sx;
+ } else if (wp->xoff < ctx->ox) {
+ /* Left not visible. */
+ xoff = 0;
+ sx = wp->sx - (ctx->ox - wp->xoff);
+ } else {
+ /* Right not visible. */
+ xoff = wp->xoff - ctx->ox;
+ sx = wp->sx - xoff;
+ }
+ if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
+ /* All visible. */
+ yoff = wp->yoff - ctx->oy;
+ sy = wp->sy;
+ } else if (wp->yoff < ctx->oy &&
+ wp->yoff + wp->sy > ctx->oy + ctx->sy) {
+ /* Both top and bottom not visible. */
+ yoff = 0;
+ sy = ctx->sy;
+ } else if (wp->yoff < ctx->oy) {
+ /* Top not visible. */
+ yoff = 0;
+ sy = wp->sy - (ctx->oy - wp->yoff);
+ } else {
+ /* Bottom not visible. */
+ yoff = wp->yoff - ctx->oy;
+ sy = wp->sy - yoff;
+ }
+
+ if (ctx->top)
+ yoff += ctx->lines;
+ px = sx / 2;
+ py = sy / 2;
+
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
len = xsnprintf(buf, sizeof buf, "%u", idx);
- if (wp->sx < len)
+ if (sx < len)
return;
colour = options_get_number(oo, "display-panes-colour");
active_colour = options_get_number(oo, "display-panes-active-colour");
- px = wp->sx / 2; py = wp->sy / 2;
- xoff = wp->xoff; yoff = wp->yoff;
-
- if (ctx->top)
- yoff += ctx->lines;
-
- if (wp->sx < len * 6 || wp->sy < 5) {
+ if (sx < len * 6 || sy < 5) {
tty_cursor(tty, xoff + px - len / 2, yoff + py);
goto draw_text;
}
@@ -661,9 +741,9 @@ screen_redraw_draw_number(struct screen_redraw_ctx *ctx, struct window_pane *wp)
}
len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
- if (wp->sx < len || wp->sy < 6)
+ if (sx < len || sy < 6)
return;
- tty_cursor(tty, xoff + wp->sx - len, yoff);
+ tty_cursor(tty, xoff + sx - len, yoff);
draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc);