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

Reply via email to