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
> tmux-users@lists.sourceforge.net
> 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
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to