Here is the diff I have been sitting on for ages, mostly written by
Jonathan Slenders.
I remembered it only doing top status lines but in fact it does
both. IIRC there are still some issues, particularly with the mouse.
I expect you will need to wait until SourceForge is synced from OpenBSD
before this will apply. Not sure when Thomas next plans to do that.
Index: cmd-set-option.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/cmd-set-option.c,v
retrieving revision 1.71
diff -u -p -r1.71 cmd-set-option.c
--- cmd-set-option.c 20 Oct 2014 22:29:25 -0000 1.71
+++ cmd-set-option.c 20 Apr 2015 14:35:26 -0000
@@ -186,6 +186,16 @@ cmd_set_option_exec(struct cmd *self, st
}
}
+ /* When the pane-status option has been changed, resize panes. */
+ if (strcmp(oe->name, "pane-status") == 0 ||
+ strcmp(oe->name, "pane-status-position") == 0) {
+ for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
+ if ((w = ARRAY_ITEM(&windows, i)) == NULL)
+ continue;
+ layout_fix_panes(w, w->sx, w->sy);
+ }
+ }
+
/* Update sizes and redraw. May not need it but meh. */
recalculate_sizes();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
Index: layout.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/layout.c,v
retrieving revision 1.23
diff -u -p -r1.23 layout.c
--- layout.c 19 Apr 2015 21:34:21 -0000 1.23
+++ layout.c 20 Apr 2015 14:35:27 -0000
@@ -34,6 +34,7 @@
int layout_resize_pane_grow(struct layout_cell *, enum layout_type, int);
int layout_resize_pane_shrink(struct layout_cell *, enum layout_type, int);
+int layout_need_status(struct layout_cell *, int);
struct layout_cell *
layout_create_cell(struct layout_cell *lcparent)
@@ -163,6 +164,30 @@ layout_fix_offsets(struct layout_cell *l
}
}
+/*
+ * Returns 1 if we need to reserve space for the pane status line. This is the
+ * case for the most upper panes only.
+ */
+int
+layout_need_status(struct layout_cell *lc, int at_top)
+{
+ struct layout_cell *first_lc;
+
+ if (lc->parent) {
+ if (lc->parent->type == LAYOUT_LEFTRIGHT)
+ return (layout_need_status(lc->parent, at_top));
+
+ if (at_top)
+ first_lc = TAILQ_FIRST(&(lc->parent->cells));
+ else
+ first_lc = TAILQ_LAST(&(lc->parent->cells),
layout_cells);
+ if (lc == first_lc)
+ return (layout_need_status(lc->parent, at_top));
+ return (0);
+ }
+ return (1);
+}
+
/* Update pane offsets and sizes based on their cells. */
void
layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
@@ -170,13 +195,25 @@ layout_fix_panes(struct window *w, u_int
struct window_pane *wp;
struct layout_cell *lc;
u_int sx, sy;
+ int shift, status, at_top;
+ status = options_get_number(&w->options, "pane-status");
+ at_top = options_get_number(&w->options, "pane-status-position") == 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((lc = wp->layout_cell) == NULL)
continue;
+
+ if (status)
+ shift = layout_need_status(lc, at_top);
+ else
+ shift = 0;
+
wp->xoff = lc->xoff;
wp->yoff = lc->yoff;
+ if (shift && at_top)
+ wp->yoff += 1;
+
/*
* Layout cells are limited by the smallest size of other cells
* within the same row or column; if this isn't the case
@@ -213,6 +250,9 @@ layout_fix_panes(struct window *w, u_int
if (sy < 2)
sy = lc->sy;
}
+
+ if (shift)
+ sy -= 1;
window_pane_resize(wp, sx, sy);
}
Index: options-table.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/options-table.c,v
retrieving revision 1.55
diff -u -p -r1.55 options-table.c
--- options-table.c 19 Apr 2015 21:34:21 -0000 1.55
+++ options-table.c 20 Apr 2015 14:35:27 -0000
@@ -592,7 +592,6 @@ const struct options_table_entry window_
.maximum = INT_MAX,
.default_num = 0
},
-
{ .name = "pane-active-border-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8,
@@ -610,6 +609,11 @@ const struct options_table_entry window_
.default_str = "fg=green"
},
+ { .name = "pane-active-status-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .default_str = "bg=green"
+ },
+
{ .name = "pane-base-index",
.type = OPTIONS_TABLE_NUMBER,
.minimum = 0,
@@ -632,6 +636,27 @@ const struct options_table_entry window_
{ .name = "pane-border-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "default"
+ },
+
+ { .name = "pane-status",
+ .type = OPTIONS_TABLE_FLAG,
+ .default_num = 1
+ },
+
+ { .name = "pane-status-format",
+ .type = OPTIONS_TABLE_STRING,
+ .default_str = "#{pane_index} \"#{pane_title}\""
+ },
+
+ { .name = "pane-status-position",
+ .type = OPTIONS_TABLE_CHOICE,
+ .choices = options_table_status_position_list,
+ .default_num = 0
+ },
+
+ { .name = "pane-status-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .default_str = "fg=green"
},
{ .name = "remain-on-exit",
Index: screen-redraw.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/screen-redraw.c,v
retrieving revision 1.30
diff -u -p -r1.30 screen-redraw.c
--- screen-redraw.c 19 Apr 2015 21:05:27 -0000 1.30
+++ screen-redraw.c 20 Apr 2015 14:35:27 -0000
@@ -24,12 +24,16 @@
int screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
int screen_redraw_cell_border(struct client *, u_int, u_int);
-int screen_redraw_check_cell(struct client *, u_int, u_int,
+int screen_redraw_check_cell(struct client *, u_int, u_int, int,
struct window_pane **);
-int screen_redraw_check_active(u_int, u_int, int, struct window *,
+int screen_redraw_check_active(u_int, u_int, int, int, struct window *,
struct window_pane *);
-void screen_redraw_draw_borders(struct client *, int, u_int);
+int screen_redraw_make_pane_status(struct client *, struct window *,
+ struct window_pane *);
+void screen_redraw_draw_pane_status(struct client *);
+
+void screen_redraw_draw_borders(struct client *, int, int, u_int);
void screen_redraw_draw_panes(struct client *, u_int);
void screen_redraw_draw_status(struct client *, u_int);
void screen_redraw_draw_number(struct client *, struct window_pane *);
@@ -100,16 +104,33 @@ screen_redraw_cell_border(struct client
/* Check if cell inside a pane. */
int
-screen_redraw_check_cell(struct client *c, u_int px, u_int py,
+screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
struct window_pane **wpp)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
int borders;
+ u_int right, line;
if (px > w->sx || py > w->sy)
return (CELL_OUTSIDE);
+ if (pane_status) {
+ TAILQ_FOREACH(wp, &w->panes, entry) {
+ if (!window_pane_visible(wp))
+ continue;
+
+ if (wp->status_position == 0)
+ line = wp->yoff - 1;
+ else
+ line = wp->yoff + wp->sy;
+ right = wp->xoff + 2 + wp->status_size - 1;
+
+ if (py == line && px >= wp->xoff + 2 && px <= right)
+ return (CELL_INSIDE);
+ }
+ }
+
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp))
continue;
@@ -135,8 +156,15 @@ screen_redraw_check_cell(struct client *
borders |= 8;
if (px <= w->sx && screen_redraw_cell_border(c, px + 1, py))
borders |= 4;
- if (py == 0 || screen_redraw_cell_border(c, px, py - 1))
- borders |= 2;
+ if (pane_status) {
+ if (py != 0 &&
+ screen_redraw_cell_border(c, px, py - 1))
+ borders |= 2;
+ } else {
+ if (py == 0 ||
+ screen_redraw_cell_border(c, px, py - 1))
+ borders |= 2;
+ }
if (py <= w->sy && screen_redraw_cell_border(c, px, py + 1))
borders |= 1;
@@ -177,8 +205,8 @@ screen_redraw_check_cell(struct client *
/* Check active pane indicator. */
int
-screen_redraw_check_active(u_int px, u_int py, int type, struct window *w,
- struct window_pane *wp)
+screen_redraw_check_active(u_int px, u_int py, int type, int pane_status,
+ struct window *w, struct window_pane *wp)
{
/* Is this off the active pane border? */
if (screen_redraw_cell_border1(w->active, px, py) != 1)
@@ -192,6 +220,10 @@ screen_redraw_check_active(u_int px, u_i
if (wp == NULL || (type == CELL_OUTSIDE || type == CELL_INSIDE))
return (1);
+ /* With status lines mark the entire line. */
+ if (pane_status)
+ return (1);
+
/* Check if the pane covers the whole width. */
if (wp->xoff == 0 && wp->sx == w->sx) {
/* This can either be the top pane or the bottom pane. */
@@ -214,7 +246,83 @@ screen_redraw_check_active(u_int px, u_i
return (0);
}
- return (type);
+ return (1);
+}
+
+/* Update pane status. */
+int
+screen_redraw_make_pane_status(struct client *c, struct window *w,
+ struct window_pane *wp)
+{
+ struct options *oo = &w->options;
+ struct grid_cell gc;
+ int utf8flag;
+ const char *fmt;
+ struct format_tree *ft;
+ char *out;
+ size_t outlen, old_size = wp->status_size;
+ struct screen_write_ctx ctx;
+
+ if (wp == w->active)
+ style_apply(&gc, oo, "pane-active-status-style");
+ else
+ style_apply(&gc, oo, "pane-status-style");
+
+ fmt = options_get_string(oo, "pane-status-format");
+
+ ft = format_create();
+ format_defaults(ft, c, NULL, NULL, wp);
+
+ screen_free(&wp->status_screen);
+ screen_init(&wp->status_screen, wp->sx, 1, 0);
+ wp->status_screen.mode = 0;
+
+ utf8flag = options_get_number(oo, "utf8");
+
+ out = format_expand(ft, fmt);
+ outlen = screen_write_cstrlen(utf8flag, "%s", out);
+ if (outlen > wp->sx - 4)
+ outlen = wp->sx - 4;
+ screen_resize(&wp->status_screen, outlen, 1, 0);
+
+ screen_write_start(&ctx, NULL, &wp->status_screen);
+ screen_write_cursormove(&ctx, 0, 0);
+ screen_write_clearline(&ctx);
+ screen_write_nputs(&ctx, outlen, &gc, utf8flag, "%s", out);
+ screen_write_stop(&ctx);
+
+ format_free(ft);
+
+ wp->status_position = options_get_number(oo, "pane-status-position");
+ wp->status_size = outlen;
+
+ return (wp->status_size != old_size);
+}
+
+/* Draw pane status. */
+void
+screen_redraw_draw_pane_status(struct client *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;
+
+ spos = options_get_number(oo, "status-position");
+ TAILQ_FOREACH(wp, &w->panes, entry) {
+ if (wp->status_position == 0)
+ yoff = wp->yoff - 1;
+ else
+ yoff = wp->yoff + wp->sy;
+ if (spos == 0)
+ yoff += 1;
+
+ tty_draw_line(tty, NULL, &wp->status_screen, 0, wp->xoff + 2,
yoff);
+
+ }
+ tty_cursor(tty, 0, 0);
}
/* Redraw entire screen. */
@@ -222,10 +330,12 @@ void
screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
int draw_borders)
{
- struct options *oo = &c->session->options;
- struct tty *tty = &c->tty;
- u_int top;
- int status, spos;
+ struct options *oo = &c->session->options;
+ struct tty *tty = &c->tty;
+ struct window *w = c->session->curw->window;
+ struct window_pane *wp;
+ u_int top;
+ int status, pane_status, spos;
/* Suspended clients should not be updated. */
if (c->flags & CLIENT_SUSPENDED)
@@ -243,12 +353,24 @@ screen_redraw_screen(struct client *c, i
if (!status)
draw_status = 0;
+ /* Update pane status lines. */
+ pane_status = options_get_number(&w->options, "pane-status");
+ if (pane_status && (draw_borders || draw_status)) {
+ TAILQ_FOREACH(wp, &w->panes, entry) {
+ if (screen_redraw_make_pane_status(c, w, wp))
+ draw_borders = draw_status = 1;
+ }
+ }
+
+ /* Draw the elements. */
if (draw_borders)
- screen_redraw_draw_borders(c, status, top);
+ screen_redraw_draw_borders(c, status, pane_status, top);
if (draw_panes)
screen_redraw_draw_panes(c, top);
if (draw_status)
screen_redraw_draw_status(c, top);
+ if (pane_status && (draw_borders || draw_status))
+ screen_redraw_draw_pane_status(c);
tty_reset(tty);
}
@@ -272,7 +394,8 @@ screen_redraw_pane(struct client *c, str
/* Draw the borders. */
void
-screen_redraw_draw_borders(struct client *c, int status, u_int top)
+screen_redraw_draw_borders(struct client *c, int status, int pane_status,
+ u_int top)
{
struct window *w = c->session->curw->window;
struct options *oo = &w->options;
@@ -316,13 +439,15 @@ screen_redraw_draw_borders(struct client
for (j = 0; j < tty->sy - status; j++) {
for (i = 0; i < tty->sx; i++) {
- type = screen_redraw_check_cell(c, i, j, &wp);
+ type = screen_redraw_check_cell(c, i, j, pane_status,
+ &wp);
if (type == CELL_INSIDE)
continue;
if (type == CELL_OUTSIDE &&
small && i > msgx && j == msgy)
continue;
- if (screen_redraw_check_active(i, j, type, w, wp))
+ if (screen_redraw_check_active(i, j, type, pane_status,
+ w, wp))
tty_attributes(tty, &active_gc, NULL);
else
tty_attributes(tty, &other_gc, NULL);
Index: server-client.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/server-client.c,v
retrieving revision 1.131
diff -u -p -r1.131 server-client.c
--- server-client.c 19 Apr 2015 21:34:21 -0000 1.131
+++ server-client.c 20 Apr 2015 14:35:28 -0000
@@ -878,7 +878,7 @@ server_client_check_redraw(struct client
{
struct session *s = c->session;
struct window_pane *wp;
- int flags, redraw;
+ int flags, masked, redraw;
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
return;
@@ -914,11 +914,13 @@ server_client_check_redraw(struct client
}
}
- if (c->flags & CLIENT_BORDERS)
+ masked = c->flags & (CLIENT_BORDERS|CLIENT_STATUS);
+ if (masked == CLIENT_BORDERS)
screen_redraw_screen(c, 0, 0, 1);
-
- if (c->flags & CLIENT_STATUS)
+ else if (masked == CLIENT_STATUS)
screen_redraw_screen(c, 0, 1, 0);
+ else if (masked != 0)
+ screen_redraw_screen(c, 0, 1, 1);
c->tty.flags |= flags;
Index: tmux.h
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
retrieving revision 1.492
diff -u -p -r1.492 tmux.h
--- tmux.h 19 Apr 2015 21:34:21 -0000 1.492
+++ tmux.h 20 Apr 2015 14:35:28 -0000
@@ -937,6 +937,10 @@ struct window_pane {
struct screen *screen;
struct screen base;
+ struct screen status_screen;
+ size_t status_size;
+ int status_position;
+
/* Saved in alternative screen mode. */
u_int saved_cx;
u_int saved_cy;
Index: window.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window.c,v
retrieving revision 1.119
diff -u -p -r1.119 window.c
--- window.c 20 Apr 2015 07:50:49 -0000 1.119
+++ window.c 20 Apr 2015 14:35:29 -0000
@@ -722,6 +722,8 @@ window_pane_create(struct window *w, u_i
screen_init(&wp->base, sx, sy, hlimit);
wp->screen = &wp->base;
+ screen_init(&wp->status_screen, 1, 1, 0);
+
input_init(wp);
return (wp);
On Mon, Apr 20, 2015 at 09:02:52AM -0400, John O'Meara wrote:
> Hi list,
>
> I had made a patch for myself to add a per-pane status bar a few weeks
> ago, and saw yesterday that there was a ticket open for a similar feature.
> Nicholas pointed out that he had already done work on this, but suggested
> I post my patch anyway.
>
> Firstly, sorry for duplicating effort. I hope this patch is helpful but I
> understand if it isn't.
>
> Secondly, the ticket does request top-of-pane title, where my patch
> currently only does bottom-of-pane, but it uses the expansion system that
> the regular status line uses, so the pane title and whatever else might be
> wanted can go there (I use pane-tty and pane-title, for example). If it is
> desired for this patch to move forward, I will work on adding a
> pane-status-position option to allow it to be placed top-of-pane (as well
> as other suggestions I receive)
>
> The patch works by decreasing the pane height by 1 when pane-status is
> enabled, and drawing the pane status line in the opened up space.
> Adjustments are made for border drawing, window selection, and mouse
> movements to work properly with the adjusted pane size. Redrawing is
> handled similar to the regular status line, in that the statuses are
> pre-rendered in memory and only sent to the screen if they differ from the
> last render. Rendering is per-client to allow things like client-tty
> expansions to work correctly.
>
> Usage is documented in the man page, and the default options move the
> pane-title from status-right to pane-status-format (leaving only the time
> in status-right), allowing for a quick example when run with default
> settings.
>
> Thanks,
>
> -- John O'Meara
> diff --git a/layout.c b/layout.c
> index b91b86c..c66ca00 100644
> --- a/layout.c
> +++ b/layout.c
> @@ -170,6 +170,9 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
> struct window_pane *wp;
> struct layout_cell *lc;
> u_int sx, sy;
> + int has_pane_status;
> +
> + has_pane_status = options_get_number(&w->options, "pane-status");
>
> TAILQ_FOREACH(wp, &w->panes, entry) {
> if ((lc = wp->layout_cell) == NULL)
> @@ -207,9 +210,9 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
> * is two because scroll regions cannot be one line.
> */
> if (lc->yoff >= wsy || lc->yoff + lc->sy < wsy)
> - sy = lc->sy;
> + sy = lc->sy - has_pane_status;
> else {
> - sy = wsy - lc->yoff;
> + sy = wsy - lc->yoff - has_pane_status;
> if (sy < 2)
> sy = lc->sy;
> }
> @@ -527,9 +530,12 @@ layout_resize_pane_mouse(struct client *c)
> struct window_pane *wp;
> struct mouse_event *m = &c->tty.mouse;
> int pane_border;
> + int has_pane_status;
>
> w = c->session->curw->window;
>
> + has_pane_status = options_get_number(&w->options, "pane-status");
> +
> pane_border = 0;
> if (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) {
> TAILQ_FOREACH(wp, &w->panes, entry) {
> @@ -538,12 +544,12 @@ layout_resize_pane_mouse(struct client *c)
>
> if (wp->xoff + wp->sx == m->lx &&
> wp->yoff <= 1 + m->ly &&
> - wp->yoff + wp->sy >= m->ly) {
> + wp->yoff + wp->sy + has_pane_status >= m->ly) {
> layout_resize_pane(wp, LAYOUT_LEFTRIGHT,
> m->x - m->lx);
> pane_border = 1;
> }
> - if (wp->yoff + wp->sy == m->ly &&
> + if (wp->yoff + wp->sy + has_pane_status == m->ly &&
> wp->xoff <= 1 + m->lx &&
> wp->xoff + wp->sx >= m->lx) {
> layout_resize_pane(wp, LAYOUT_TOPBOTTOM,
> @@ -557,8 +563,8 @@ layout_resize_pane_mouse(struct client *c)
> TAILQ_FOREACH(wp, &w->panes, entry) {
> if ((wp->xoff + wp->sx == m->x &&
> wp->yoff <= 1 + m->y &&
> - wp->yoff + wp->sy >= m->y) ||
> - (wp->yoff + wp->sy == m->y &&
> + wp->yoff + wp->sy + has_pane_status >= m->y) ||
> + (wp->yoff + wp->sy + has_pane_status == m->y &&
> wp->xoff <= 1 + m->x &&
> wp->xoff + wp->sx >= m->x)) {
> pane_border = 1;
> diff --git a/options-table.c b/options-table.c
> index 2bcf29b..be9af3f 100644
> --- a/options-table.c
> +++ b/options-table.c
> @@ -396,7 +396,7 @@ const struct options_table_entry session_options_table[]
> = {
>
> { .name = "status-right",
> .type = OPTIONS_TABLE_STRING,
> - .default_str = " \"#{=21:pane_title}\" %H:%M %d-%b-%y"
> + .default_str = "%H:%M %d-%b-%y"
> },
>
> { .name = "status-right-attr",
> @@ -652,6 +652,39 @@ const struct options_table_entry window_options_table[]
> = {
> .default_str = "default"
> },
>
> + { .name = "pane-status",
> + .type = OPTIONS_TABLE_FLAG,
> + .default_num = 1
> + },
> +
> + { .name = "pane-status-attr",
> + .type = OPTIONS_TABLE_ATTRIBUTES,
> + .default_num = 0,
> + .style = "pane-status-style"
> + },
> +
> + { .name = "pane-status-bg",
> + .type = OPTIONS_TABLE_COLOUR,
> + .default_num = 2,
> + .style = "pane-status-style"
> + },
> +
> + { .name = "pane-status-fg",
> + .type = OPTIONS_TABLE_COLOUR,
> + .default_num = 0,
> + .style = "pane-status-style"
> + },
> +
> + { .name = "pane-status-format",
> + .type = OPTIONS_TABLE_STRING,
> + .default_str = "[#T]"
> + },
> +
> + { .name = "pane-status-style",
> + .type = OPTIONS_TABLE_STYLE,
> + .default_str = "default"
> + },
> +
> { .name = "remain-on-exit",
> .type = OPTIONS_TABLE_FLAG,
> .default_num = 0
> diff --git a/resize.c b/resize.c
> index 9ad73c8..edf44d5 100644
> --- a/resize.c
> +++ b/resize.c
> @@ -128,8 +128,16 @@ recalculate_sizes(void)
> forced |= WINDOW_FORCEHEIGHT;
> }
>
> +#if 0 /* This optimization to not resize panes if the window size doesn't
> + change fails to handle the case where pane sizes may have changed
> + due to options like 'pane-status' changing. Unfortunately, we
> + can't at this point know if this function was called because of an
> + option change, let alone specific option changes. For now, we'll
> + just skip the optimization and take the computational hit rather
> + than have a stale display. */
> if (w->sx == ssx && w->sy == ssy)
> continue;
> +#endif
> log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx,
> w->sy);
>
> diff --git a/screen-redraw.c b/screen-redraw.c
> index c2b2ece..a36a2fe 100644
> --- a/screen-redraw.c
> +++ b/screen-redraw.c
> @@ -54,13 +54,17 @@ void screen_redraw_draw_number(struct client *,
> struct window_pane *);
> int
> screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
> {
> + int has_pane_status;
> +
> + has_pane_status = options_get_number(&wp->window->options,
> "pane-status");
> +
> /* Inside pane. */
> if (px >= wp->xoff && px < wp->xoff + wp->sx &&
> - py >= wp->yoff && py < wp->yoff + wp->sy)
> + py >= wp->yoff && py < wp->yoff + wp->sy + has_pane_status)
> return (0);
>
> /* Left/right borders. */
> - if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= wp->yoff + wp->sy) {
> + if ((wp->yoff == 0 || py >= wp->yoff - 1 + has_pane_status) && py <=
> wp->yoff + wp->sy + has_pane_status) {
> if (wp->xoff != 0 && px == wp->xoff - 1)
> return (1);
> if (px == wp->xoff + wp->sx)
> @@ -71,7 +75,7 @@ screen_redraw_cell_border1(struct window_pane *wp, u_int
> px, u_int py)
> if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= wp->xoff + wp->sx) {
> if (wp->yoff != 0 && py == wp->yoff - 1)
> return (1);
> - if (py == wp->yoff + wp->sy)
> + if (py == wp->yoff + wp->sy + has_pane_status)
> return (1);
> }
>
> @@ -106,6 +110,9 @@ screen_redraw_check_cell(struct client *c, u_int px,
> u_int py,
> struct window *w = c->session->curw->window;
> struct window_pane *wp;
> int borders;
> + int has_pane_status;
> +
> + has_pane_status = options_get_number(&w->options, "pane-status");
>
> if (px > w->sx || py > w->sy)
> return (CELL_OUTSIDE);
> @@ -119,7 +126,7 @@ screen_redraw_check_cell(struct client *c, u_int px,
> u_int py,
> if ((wp->xoff != 0 && px < wp->xoff - 1) ||
> px > wp->xoff + wp->sx ||
> (wp->yoff != 0 && py < wp->yoff - 1) ||
> - py > wp->yoff + wp->sy)
> + py > wp->yoff + wp->sy + has_pane_status)
> continue;
>
> /* If definitely inside, return so. */
> @@ -180,6 +187,10 @@ int
> screen_redraw_check_active(u_int px, u_int py, int type, struct window *w,
> struct window_pane *wp)
> {
> + int has_pane_status;
> +
> + has_pane_status = options_get_number(&wp->window->options,
> "pane-status");
> +
> /* Is this off the active pane border? */
> if (screen_redraw_cell_border1(w->active, px, py) != 1)
> return (0);
> @@ -204,7 +215,7 @@ screen_redraw_check_active(u_int px, u_int py, int type,
> struct window *w,
> }
>
> /* Check if the pane covers the whole height. */
> - if (wp->yoff == 0 && wp->sy == w->sy) {
> + if (wp->yoff == 0 && wp->sy + has_pane_status == w->sy) {
> /* This can either be the left pane or the right pane. */
> if (wp->xoff == 0) { /* left pane */
> if (wp == w->active)
> @@ -217,6 +228,24 @@ screen_redraw_check_active(u_int px, u_int py, int type,
> struct window *w,
> return (type);
> }
>
> +void
> +screen_redraw_draw_pane_status(struct client *c, u_int top)
> +{
> + struct window *w = c->session->curw->window;
> + struct window_pane *wp;
> + struct pane_status *ps = TAILQ_FIRST(&c->pane_statuses);
> +
> + TAILQ_FOREACH(wp, &w->panes, entry) {
> + if (!window_pane_visible(wp))
> + continue;
> + if (!ps) {
> + fatalx("pane status not found");
> + }
> + tty_draw_line(&c->tty, &ps->status, 0, wp->xoff, top + wp->yoff
> + wp->sy);
> + ps = TAILQ_NEXT(ps, entry);
> + }
> +}
> +
> /* Redraw entire screen. */
> void
> screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
> @@ -226,6 +255,7 @@ screen_redraw_screen(struct client *c, int draw_panes,
> int draw_status,
> struct tty *tty = &c->tty;
> u_int top;
> int status, spos;
> + int draw_pane_status;
>
> /* Suspended clients should not be updated. */
> if (c->flags & CLIENT_SUSPENDED)
> @@ -238,6 +268,10 @@ screen_redraw_screen(struct client *c, int draw_panes,
> int draw_status,
> else
> status = options_get_number(oo, "status");
> top = 0;
> + if (draw_status &&
> options_get_number(&c->session->curw->window->options, "pane-status"))
> + draw_pane_status = 1;
> + else
> + draw_pane_status = 0;
> if (status && spos == 0)
> top = 1;
> if (!status)
> @@ -249,6 +283,9 @@ screen_redraw_screen(struct client *c, int draw_panes,
> int draw_status,
> screen_redraw_draw_panes(c, top);
> if (draw_status)
> screen_redraw_draw_status(c, top);
> + if (draw_pane_status){
> + screen_redraw_draw_pane_status(c, top);
> + }
> tty_reset(tty);
> }
>
> diff --git a/server-client.c b/server-client.c
> index f7ce35c..fa278af 100644
> --- a/server-client.c
> +++ b/server-client.c
> @@ -749,6 +749,7 @@ server_client_check_redraw(struct client *c)
> redraw = status_prompt_redraw(c);
> else
> redraw = status_redraw(c);
> + redraw |= pane_status_redraw(c);
> if (!redraw)
> c->flags &= ~CLIENT_STATUS;
> }
> diff --git a/status.c b/status.c
> index 5f8895f..b7546bb 100644
> --- a/status.c
> +++ b/status.c
> @@ -38,7 +38,7 @@ void status_job_free(void *);
> void status_job_callback(struct job *);
> char *status_print(struct client *, struct winlink *, time_t,
> struct grid_cell *);
> -char *status_replace(struct client *, struct winlink *, const char *,
> time_t);
> +char *status_replace(struct client *, struct winlink *, struct window_pane
> *wp, const char *, time_t);
> void status_replace1(struct client *, char **, char **, char *, size_t);
> void status_message_callback(int, short, void *);
>
> @@ -87,7 +87,7 @@ status_redraw_get_left(struct client *c, time_t t, int
> utf8flag,
> style_apply_update(gc, &s->options, "status-left-style");
>
> template = options_get_string(&s->options, "status-left");
> - left = status_replace(c, NULL, template, t);
> + left = status_replace(c, NULL, NULL, template, t);
>
> *size = options_get_number(&s->options, "status-left-length");
> leftlen = screen_write_cstrlen(utf8flag, "%s", left);
> @@ -109,7 +109,7 @@ status_redraw_get_right(struct client *c, time_t t, int
> utf8flag,
> style_apply_update(gc, &s->options, "status-right-style");
>
> template = options_get_string(&s->options, "status-right");
> - right = status_replace(c, NULL, template, t);
> + right = status_replace(c, NULL, NULL, template, t);
>
> *size = options_get_number(&s->options, "status-right-length");
> rightlen = screen_write_cstrlen(utf8flag, "%s", right);
> @@ -362,6 +362,86 @@ out:
> return (1);
> }
>
> +/* Draw status for panes */
> +int
> +pane_status_redraw(struct client *c)
> +{
> + struct screen_write_ctx ctx;
> + int utf8flag;
> + struct grid_cell stdgc;
> + char *msg;
> + struct window *w = c->session->curw->window;
> + struct window_pane *wp;
> + struct pane_statuses old_pane_statuses;
> + struct pane_status *pane_status;
> + struct pane_status *t;
> + int diff = 0;
> + unsigned int len;
> +
> + if (options_get_number(&w->options, "pane-status") == 0) {
> + return 0;
> + }
> +
> + memcpy(&old_pane_statuses, &c->pane_statuses, sizeof old_pane_statuses);
> + TAILQ_INIT(&c->pane_statuses);
> +
> + utf8flag = options_get_number(&c->session->options, "status-utf8");
> +
> + /* Create set of statuses for each pane */
> + TAILQ_FOREACH(wp, &w->panes, entry) {
> + if (!window_pane_visible(wp))
> + continue;
> + pane_status = malloc(sizeof *pane_status);
> + if (!pane_status) {
> + continue;
> + }
> + memcpy(&stdgc, &grid_default_cell, sizeof stdgc);
> + colour_set_fg(&stdgc, options_get_number(&wp->window->options,
> "pane-status-fg"));
> + colour_set_bg(&stdgc, options_get_number(&wp->window->options,
> "pane-status-bg"));
> + stdgc.attr |= options_get_number(&wp->window->options,
> "pane-status-attr");
> + screen_init(&pane_status->status, wp->sx, 1, 0);
> + msg = status_replace(c, NULL, wp,
> options_get_string(&wp->window->options, "pane-status-format"), time(NULL));
> + len = screen_write_strlen(utf8flag, "%s", msg);
> + if (len > wp->sx) {
> + len = wp->sx;
> + }
> + screen_write_start(&ctx, NULL, &pane_status->status);
> + screen_write_cursormove(&ctx, 0, 0);
> + screen_write_cnputs(&ctx, len, &stdgc, utf8flag, "%s", msg);
> + screen_write_stop(&ctx);
> + free(msg);
> + TAILQ_INSERT_TAIL(&c->pane_statuses, pane_status, entry);
> + }
> +
> + /* Check if any of the status lines have changed, or if the number
> + * of status lines have changed. */
> + {
> + struct pane_status *old;
> + struct pane_status *new;
> + old = TAILQ_FIRST(&old_pane_statuses);
> + new = TAILQ_FIRST(&c->pane_statuses);
> + while (old != TAILQ_END(&old_pane_statuses) && new !=
> TAILQ_END(&c->pane_statuses)) {
> + if (grid_compare(old->status.grid, new->status.grid) !=
> 0) {
> + //screen_free(&old_status);
> + diff = 1;
> + }
> + //screen_free(&old_status);
> + old = TAILQ_NEXT(old, entry);
> + new = TAILQ_NEXT(new, entry);
> + }
> + if (old != TAILQ_END(&old_pane_statuses) || new !=
> TAILQ_END(&c->pane_statuses)) {
> + diff = 1;
> + }
> + }
> + /* discard old */
> + TAILQ_FOREACH_SAFE(pane_status, &old_pane_statuses, entry, t) {
> + screen_free(&pane_status->status);
> + free(pane_status);
> + }
> + return diff;
> +}
> +
> +
> /* Replace a single special sequence (prefixed by #). */
> void
> status_replace1(struct client *c, char **iptr, char **optr, char *out,
> @@ -431,7 +511,7 @@ skip_to:
>
> /* Replace special sequences in fmt. */
> char *
> -status_replace(struct client *c, struct winlink *wl, const char *fmt, time_t
> t)
> +status_replace(struct client *c, struct winlink *wl, struct window_pane *wp,
> const char *fmt, time_t t)
> {
> static char out[BUFSIZ];
> char in[BUFSIZ], ch, *iptr, *optr, *expanded;
> @@ -461,7 +541,7 @@ status_replace(struct client *c, struct winlink *wl,
> const char *fmt, time_t t)
> *optr = '\0';
>
> ft = format_create();
> - format_defaults(ft, c, NULL, wl, NULL);
> + format_defaults(ft, c, NULL, wl, wp);
> expanded = format_expand(ft, out);
> format_free(ft);
> return (expanded);
> @@ -626,7 +706,7 @@ status_print(struct client *c, struct winlink *wl, time_t
> t,
> else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE))
> style_apply_update(gc, oo, "window-status-activity-style");
>
> - text = status_replace(c, wl, fmt, t);
> + text = status_replace(c, wl, NULL, fmt, t);
> return (text);
> }
>
> diff --git a/tmux.1 b/tmux.1
> index 8a0879b..b277376 100644
> --- a/tmux.1
> +++ b/tmux.1
> @@ -2617,7 +2617,7 @@ Set the position of the status line.
> Display
> .Ar string
> to the right of the status bar.
> -By default, the current window title in double quotes, the date and the time
> +By default, the date and the time
> are shown.
> As with
> .Ic status-left ,
> @@ -2918,6 +2918,33 @@ see the
> option.
> Attributes are ignored.
> .Pp
> +.It Xo Ic pane-status
> +.Op Ic on | off
> +.Xc
> +Show or hide a status line at the bottom of each pane.
> +.Pp
> +.It Ic pane-status-format Ar string
> +Display
> +.Ar string
> +in the status bar of each pane in the window.
> +By default, the pane title is shown in brackets.
> +As with
> +.Ic status-left ,
> +.Ar string
> +will be passed to
> +.Xr strftime 3 ,
> +character pairs are replaced, and UTF-8 is dependent on the
> +.Ic status-utf8
> +option.
> +.Pp
> +.It Ic pane-status-style Ar style
> +Set the pane status line style.
> +For how to specify
> +.Ar style ,
> +see the
> +.Ic message-command-style
> +opption.
> +.Pp
> .It Xo Ic remain-on-exit
> .Op Ic on | off
> .Xc
> diff --git a/tmux.h b/tmux.h
> index e296ac7..bc1e659 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -923,6 +923,12 @@ TAILQ_HEAD(window_panes, window_pane);
> RB_HEAD(window_pane_tree, window_pane);
> ARRAY_DECL(window_pane_list, struct window_pane *);
>
> +struct pane_status {
> + struct screen status;
> + TAILQ_ENTRY(pane_status) entry;
> +};
> +TAILQ_HEAD(pane_statuses, pane_status);
> +
> /* Window structure. */
> struct window {
> u_int id;
> @@ -1283,6 +1289,7 @@ struct client {
> struct status_out_tree status_new;
> struct timeval status_timer;
> struct screen status;
> + struct pane_statuses pane_statuses;
>
> #define CLIENT_TERMINAL 0x1
> #define CLIENT_PREFIX 0x2
> @@ -1923,6 +1930,7 @@ void status_free_jobs(struct status_out_tree *);
> void status_update_jobs(struct client *);
> void status_set_window_at(struct client *, u_int);
> int status_redraw(struct client *);
> +int pane_status_redraw(struct client *c);
> void printflike(2, 3) status_message_set(struct client *, const char *, ...);
> void status_message_clear(struct client *);
> int status_message_redraw(struct client *);
> @@ -2058,6 +2066,7 @@ void screen_write_setselection(struct
> screen_write_ctx *, u_char *, u_int);
> void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int);
>
> /* screen-redraw.c */
> +void screen_redraw_draw_pane_status(struct client *c, u_int top);
> void screen_redraw_screen(struct client *, int, int, int);
> void screen_redraw_pane(struct client *, struct window_pane *);
>
> diff --git a/window.c b/window.c
> index fff2cfc..b7e6f53 100644
> --- a/window.c
> +++ b/window.c
> @@ -1180,6 +1180,9 @@ window_pane_find_up(struct window_pane *wp)
> u_int edge, left, right, end;
> struct window_pane_list list;
> int found;
> + int has_pane_status;
> +
> + has_pane_status = options_get_number(&wp->window->options,
> "pane-status");
>
> if (wp == NULL || !window_pane_visible(wp))
> return (NULL);
> @@ -1195,7 +1198,7 @@ window_pane_find_up(struct window_pane *wp)
> TAILQ_FOREACH(next, &wp->window->panes, entry) {
> if (next == wp || !window_pane_visible(next))
> continue;
> - if (next->yoff + next->sy + 1 != edge)
> + if (next->yoff + next->sy + 1 + has_pane_status != edge)
> continue;
> end = next->xoff + next->sx - 1;
>
> @@ -1223,12 +1226,15 @@ window_pane_find_down(struct window_pane *wp)
> u_int edge, left, right, end;
> struct window_pane_list list;
> int found;
> + int has_pane_status;
> +
> + has_pane_status = options_get_number(&wp->window->options,
> "pane-status");
>
> if (wp == NULL || !window_pane_visible(wp))
> return (NULL);
> ARRAY_INIT(&list);
>
> - edge = wp->yoff + wp->sy + 1;
> + edge = wp->yoff + wp->sy + 1 + has_pane_status;
> if (edge >= wp->window->sy)
> edge = 0;
>
> ------------------------------------------------------------------------------
> BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
> Develop your own process in accordance with the BPMN 2 standard
> Learn Process modeling best practices with Bonita BPM through live exercises
> http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
> source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
> _______________________________________________
> tmux-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/tmux-users
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
tmux-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-users