Here is latest, notably fixing a redraw bug with status lines at bottom and merging pane-status and pane-status-position.
Index: cmd-set-option.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/cmd-set-option.c,v retrieving revision 1.74 diff -u -p -r1.74 cmd-set-option.c --- cmd-set-option.c 24 Apr 2015 23:17:11 -0000 1.74 +++ cmd-set-option.c 25 Apr 2015 21:03:17 -0000 @@ -183,6 +183,12 @@ 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) { + RB_FOREACH(w, windows, &windows) + layout_fix_panes(w, w->sx, w->sy); + } + /* Update sizes and redraw. May not need it but meh. */ recalculate_sizes(); TAILQ_FOREACH(c, &clients, entry) { 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 25 Apr 2015 21:03:17 -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 = (status == 1); TAILQ_FOREACH(wp, &w->panes, entry) { if ((lc = wp->layout_cell) == NULL) continue; + + if (status != 0) + 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 25 Apr 2015 21:03:17 -0000 @@ -51,6 +51,9 @@ const char *options_table_status_positio const char *options_table_bell_action_list[] = { "none", "any", "current", NULL }; +const char *options_table_pane_status_list[] = { + "off", "top", "bottom", NULL +}; /* Server options. */ const struct options_table_entry server_options_table[] = { @@ -610,6 +613,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 +640,22 @@ const struct options_table_entry window_ { .name = "pane-border-style", .type = OPTIONS_TABLE_STYLE, .default_str = "default" + }, + + { .name = "pane-status", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_pane_status_list, + .default_num = 0 + }, + + { .name = "pane-status-format", + .type = OPTIONS_TABLE_STRING, + .default_str = "#{pane_index} \"#{pane_title}\"" + }, + + { .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 25 Apr 2015 21:03:17 -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 *, int); + +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 *); @@ -50,6 +54,10 @@ void screen_redraw_draw_number(struct cl #define CELL_BORDERS " xqlkmjwvtun~" +#define CELL_STATUS_OFF 0 +#define CELL_STATUS_TOP 1 +#define CELL_STATUS_BOTTOM 2 + /* Check if cell is on the border of a particular pane. */ int screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py) @@ -100,16 +108,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 != CELL_STATUS_OFF) { + TAILQ_FOREACH(wp, &w->panes, entry) { + if (!window_pane_visible(wp)) + continue; + + if (pane_status == CELL_STATUS_TOP) + 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 +160,13 @@ 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 == CELL_STATUS_TOP) { + 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 +207,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 +222,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 != CELL_STATUS_OFF) + 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 +248,81 @@ 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_size = outlen; + return (wp->status_size != old_size); +} + +/* Draw pane status. */ +void +screen_redraw_draw_pane_status(struct client *c, int pane_status) +{ + 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 (pane_status == CELL_STATUS_TOP) + 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 != CELL_STATUS_OFF && (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 != CELL_STATUS_OFF && (draw_borders || draw_status)) + screen_redraw_draw_pane_status(c, pane_status); 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.136 diff -u -p -r1.136 server-client.c --- server-client.c 25 Apr 2015 18:33:59 -0000 1.136 +++ server-client.c 25 Apr 2015 21:03:18 -0000 @@ -876,7 +876,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; @@ -912,11 +912,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.1 =================================================================== RCS file: /cvs/src/usr.bin/tmux/tmux.1,v retrieving revision 1.422 diff -u -p -r1.422 tmux.1 --- tmux.1 21 Apr 2015 22:32:40 -0000 1.422 +++ tmux.1 25 Apr 2015 21:03:19 -0000 @@ -2954,6 +2954,9 @@ see the option. Attributes are ignored. .Pp +.It Ic pane-active-status-style +Set the style of the active pane's status line. +.Pp .It Ic pane-base-index Ar index Like .Ic base-index , @@ -2967,6 +2970,18 @@ see the .Ic message-command-style option. Attributes are ignored. +.Pp +.It Xo Ic pane-status +.Op Ic off | top | bottom +.Xc +Turn pane status lines off or set their position. +A pane's status line is shown on the pane border. +.Pp +.It Ic pane-status-format Ar format +Set the text shown in pane status lines. +.Pp +.It Ic pane-status-style Ar style +Set the style of pane status lines. .Pp .It Xo Ic remain-on-exit .Op Ic on | off Index: tmux.h =================================================================== RCS file: /cvs/src/usr.bin/tmux/tmux.h,v retrieving revision 1.501 diff -u -p -r1.501 tmux.h --- tmux.h 25 Apr 2015 18:33:59 -0000 1.501 +++ tmux.h 25 Apr 2015 21:03:19 -0000 @@ -936,6 +936,9 @@ struct window_pane { struct screen *screen; struct screen base; + struct screen status_screen; + size_t status_size; + /* 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.126 diff -u -p -r1.126 window.c --- window.c 25 Apr 2015 18:56:05 -0000 1.126 +++ window.c 25 Apr 2015 21:03:19 -0000 @@ -732,6 +732,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 Sat, Apr 25, 2015 at 09:31:44PM +0100, Nicholas Marriott wrote: > Hi > > I like the other diff a bit more than yours so I think I will go with > it, does it meet your needs too, or any comments? > > > > 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 > > tmux-users@lists.sourceforge.net > > https://lists.sourceforge.net/lists/listinfo/tmux-users > ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users