From 7247553c77eb9dae8eab1b7ee12b10fc70cca69c Mon Sep 17 00:00:00 2001
From: nicm <nicm>
Date: Fri, 30 Jun 2017 22:24:08 +0000
Subject: [PATCH 1/3] Try to show a better preview of sessions and windows in
 tree mode.

---
 screen-write.c  |  29 +++++++++-
 tmux.h          |   3 +-
 window-client.c |   2 +-
 window-tree.c   | 149 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 177 insertions(+), 6 deletions(-)

diff --git a/screen-write.c b/screen-write.c
index 6f0f6a22..88f03a31 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -387,9 +387,9 @@ screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px,
 	}
 }
 
-/* Draw a line on screen. */
+/* Draw a horizontal line on screen. */
 void
-screen_write_line(struct screen_write_ctx *ctx, u_int nx, int left, int right)
+screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right)
 {
 	struct screen		*s = ctx->s;
 	struct grid_cell	 gc;
@@ -409,6 +409,31 @@ screen_write_line(struct screen_write_ctx *ctx, u_int nx, int left, int right)
 	screen_write_cursormove(ctx, cx, cy);
 }
 
+/* Draw a horizontal line on screen. */
+void
+screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom) 
+{
+	struct screen		*s = ctx->s;
+	struct grid_cell	 gc;
+	u_int			 cx, cy, i;
+
+	cx = s->cx;
+	cy = s->cy;
+
+	memcpy(&gc, &grid_default_cell, sizeof gc);
+	gc.attr |= GRID_ATTR_CHARSET;
+
+	screen_write_putc(ctx, &gc, top ? 'w' : 'x');
+	for (i = 1; i < ny - 1; i++) {
+		screen_write_cursormove(ctx, cx, cy + i);
+		screen_write_putc(ctx, &gc, 'x');
+	}
+	screen_write_cursormove(ctx, cx, cy + ny);
+	screen_write_putc(ctx, &gc, bottom ? 'v' : 'x');
+
+	screen_write_cursormove(ctx, cx, cy);
+}
+
 /* Draw a box on screen. */
 void
 screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny)
diff --git a/tmux.h b/tmux.h
index 2fdccd2a..742f7846 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2019,7 +2019,8 @@ void	 screen_write_putc(struct screen_write_ctx *, const struct grid_cell *,
 	     u_char);
 void	 screen_write_copy(struct screen_write_ctx *, struct screen *, u_int,
 	     u_int, u_int, u_int, bitstr_t *, const struct grid_cell *);
-void	 screen_write_line(struct screen_write_ctx *, u_int, int, int);
+void	 screen_write_hline(struct screen_write_ctx *, u_int, int, int);
+void	 screen_write_vline(struct screen_write_ctx *, u_int, int, int);
 void	 screen_write_box(struct screen_write_ctx *, u_int, u_int);
 void	 screen_write_preview(struct screen_write_ctx *, struct screen *, u_int,
 	     u_int);
diff --git a/window-client.c b/window-client.c
index 9da8431e..2e72a398 100644
--- a/window-client.c
+++ b/window-client.c
@@ -230,7 +230,7 @@ window_client_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
 	screen_write_preview(&ctx, &wp->base, sx, sy - 3);
 
 	screen_write_cursormove(&ctx, 0, sy - 2);
-	screen_write_line(&ctx, sx, 0, 0);
+	screen_write_hline(&ctx, sx, 0, 0);
 
 	screen_write_cursormove(&ctx, 0, sy - 1);
 	if (c->old_status != NULL)
diff --git a/window-tree.c b/window-tree.c
index 210b8b04..e6851531 100644
--- a/window-tree.c
+++ b/window-tree.c
@@ -408,6 +408,140 @@ window_tree_build(void *modedata, u_int sort_type, uint64_t *tag,
 	}
 }
 
+static void
+window_tree_draw_session(struct session *s, struct screen_write_ctx *ctx,
+    u_int sx, u_int sy)
+{
+	struct options		*oo = s->options;
+	struct winlink		*wl;
+	struct window		*w;
+	u_int			 i, n, each, width, left;
+	struct grid_cell	 gc;
+	int			 colour, active_colour;
+	char			*label;
+	size_t			 len;
+
+	if (sx < 6)
+		return;
+	n = winlink_count(&s->windows);
+
+	memcpy(&gc, &grid_default_cell, sizeof gc);
+	colour = options_get_number(oo, "display-panes-colour");
+	active_colour = options_get_number(oo, "display-panes-active-colour");
+
+	each = sx / n;
+	if (each < 24) {
+		n = (sx - 6) / 24;
+		each = (sx - 6) / n;
+		left = sx - (n * each);
+
+		screen_write_cursormove(ctx, sx - left, 0);
+		screen_write_vline(ctx, sy, 0, 0);
+		screen_write_cursormove(ctx, sx - left + left / 2, sy / 2);
+		screen_write_puts(ctx, &grid_default_cell, "...");
+
+		if (sx == left)
+			return;
+		left = 0;
+	} else
+		left = sx - (n * each);
+
+	wl = RB_MIN(winlinks, &s->windows);
+	for (i = 0; i < n; i++) {
+		if (wl == s->curw)
+			gc.fg = active_colour;
+		else
+			gc.fg = colour;
+		if (i == n - 1)
+			width = each + left;
+		else
+			width = each - 1;
+		w = wl->window;
+
+		screen_write_cursormove(ctx, i * each, 0);
+		screen_write_preview(ctx, &w->active->base, width, sy);
+
+		xasprintf(&label, " %u:%s ", wl->idx, w->name);
+		if (strlen(label) > width)
+			xasprintf(&label, " %u ", wl->idx);
+		len = strlen(label) / 2;
+		screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
+		screen_write_puts(ctx, &gc, "%s", label);
+		free(label);
+
+		if (i != n - 1) {
+			screen_write_cursormove(ctx, i * each + width, 0);
+			screen_write_vline(ctx, sy, 0, 0);
+		}
+		wl = RB_NEXT(winlinks, &s->windows, wl);
+	}
+}
+
+static void
+window_tree_draw_window(struct session *s, struct window *w,
+    struct screen_write_ctx *ctx, u_int sx, u_int sy)
+{
+	struct options		*oo = s->options;
+	struct window_pane	*wp;
+	u_int			 i, n, each, width, left;
+	struct grid_cell	 gc;
+	int			 colour, active_colour;
+	char			*label;
+	size_t			 len;
+
+	if (sx < 6)
+		return;
+	n = window_count_panes(w);
+
+	memcpy(&gc, &grid_default_cell, sizeof gc);
+	colour = options_get_number(oo, "display-panes-colour");
+	active_colour = options_get_number(oo, "display-panes-active-colour");
+
+	each = sx / n;
+	if (each < 24) {
+		n = (sx - 6) / 24;
+		each = (sx - 6) / n;
+		left = sx - (n * each);
+
+		screen_write_cursormove(ctx, sx - left, 0);
+		screen_write_vline(ctx, sy, 0, 0);
+		screen_write_cursormove(ctx, sx - left + left / 2, sy / 2);
+		screen_write_puts(ctx, &grid_default_cell, "...");
+
+		if (sx == left)
+			return;
+		left = 0;
+	} else
+		left = sx - (n * each);
+
+	wp = TAILQ_FIRST(&w->panes);
+	for (i = 0; i < n; i++) {
+		if (wp == w->active)
+			gc.fg = active_colour;
+		else
+			gc.fg = colour;
+		if (i == n - 1)
+			width = each + left;
+		else
+			width = each - 1;
+
+		screen_write_cursormove(ctx, i * each, 0);
+		screen_write_preview(ctx, &wp->base, width, sy);
+
+		xasprintf(&label, " %u ", i);
+		len = strlen(label) / 2;
+		screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
+		screen_write_puts(ctx, &gc, "%s", label);
+		free(label);
+
+		if (i != n - 1) {
+			screen_write_cursormove(ctx, i * each + width, 0);
+			screen_write_vline(ctx, sy, 0, 0);
+		}
+		wp = TAILQ_NEXT(wp, entry);
+	}
+}
+
 static struct screen *
 window_tree_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
 {
@@ -423,10 +557,21 @@ window_tree_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy)
 		return (NULL);
 
 	screen_init(&s, sx, sy, 0);
-
 	screen_write_start(&ctx, NULL, &s);
 
-	screen_write_preview(&ctx, &wp->base, sx, sy);
+	switch (item->type) {
+	case WINDOW_TREE_NONE:
+		return (0);
+	case WINDOW_TREE_SESSION:
+		window_tree_draw_session(sp, &ctx, sx, sy);
+		break;
+	case WINDOW_TREE_WINDOW:
+		window_tree_draw_window(sp, wlp->window, &ctx, sx, sy);
+		break;
+	case WINDOW_TREE_PANE:
+		screen_write_preview(&ctx, &wp->base, sx, sy);
+		break;
+	}
 
 	screen_write_stop(&ctx);
 	return (&s);

From b565644c81a3c79580323b162806b52b74e2a2a9 Mon Sep 17 00:00:00 2001
From: nicm <nicm>
Date: Fri, 30 Jun 2017 22:36:11 +0000
Subject: [PATCH 2/3] Fix previous when we end up able to show no panes.

---
 window-tree.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/window-tree.c b/window-tree.c
index e6851531..d034e3ed 100644
--- a/window-tree.c
+++ b/window-tree.c
@@ -432,6 +432,8 @@ window_tree_draw_session(struct session *s, struct screen_write_ctx *ctx,
 	each = sx / n;
 	if (each < 24) {
 		n = (sx - 6) / 24;
+		if (n == 0)
+			n = 1;
 		each = (sx - 6) / n;
 		left = sx - (n * each);
 
@@ -440,7 +442,7 @@ window_tree_draw_session(struct session *s, struct screen_write_ctx *ctx,
 		screen_write_cursormove(ctx, sx - left + left / 2, sy / 2);
 		screen_write_puts(ctx, &grid_default_cell, "...");
 
-		if (sx == left)
+		if (each == 0)
 			return;
 		left = 0;
 	} else
@@ -466,7 +468,8 @@ window_tree_draw_session(struct session *s, struct screen_write_ctx *ctx,
 			xasprintf(&label, " %u ", wl->idx);
 		len = strlen(label) / 2;
 		screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
-		screen_write_puts(ctx, &gc, "%s", label);
+		if (len <= width)
+			screen_write_puts(ctx, &gc, "%s", label);
 		free(label);
 
 		if (i != n - 1) {
@@ -500,6 +503,8 @@ window_tree_draw_window(struct session *s, struct window *w,
 	each = sx / n;
 	if (each < 24) {
 		n = (sx - 6) / 24;
+		if (n == 0)
+			n = 1;
 		each = (sx - 6) / n;
 		left = sx - (n * each);
 
@@ -508,7 +513,7 @@ window_tree_draw_window(struct session *s, struct window *w,
 		screen_write_cursormove(ctx, sx - left + left / 2, sy / 2);
 		screen_write_puts(ctx, &grid_default_cell, "...");
 
-		if (sx == left)
+		if (each == 0)
 			return;
 		left = 0;
 	} else
@@ -531,7 +536,8 @@ window_tree_draw_window(struct session *s, struct window *w,
 		xasprintf(&label, " %u ", i);
 		len = strlen(label) / 2;
 		screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
-		screen_write_puts(ctx, &gc, "%s", label);
+		if (len <= width)
+			screen_write_puts(ctx, &gc, "%s", label);
 		free(label);
 
 		if (i != n - 1) {

From fa677fc0e15e32094d3e6b6816acd88e6bfbb429 Mon Sep 17 00:00:00 2001
From: nicm <nicm>
Date: Fri, 30 Jun 2017 22:37:35 +0000
Subject: [PATCH 3/3] Don't write over right border.

---
 window-tree.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/window-tree.c b/window-tree.c
index d034e3ed..71a93761 100644
--- a/window-tree.c
+++ b/window-tree.c
@@ -468,7 +468,7 @@ window_tree_draw_session(struct session *s, struct screen_write_ctx *ctx,
 			xasprintf(&label, " %u ", wl->idx);
 		len = strlen(label) / 2;
 		screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
-		if (len <= width)
+		if (len < width)
 			screen_write_puts(ctx, &gc, "%s", label);
 		free(label);
 
@@ -536,7 +536,7 @@ window_tree_draw_window(struct session *s, struct window *w,
 		xasprintf(&label, " %u ", i);
 		len = strlen(label) / 2;
 		screen_write_cursormove(ctx, i * each + each / 2 - len, sy / 2);
-		if (len <= width)
+		if (len < width)
 			screen_write_puts(ctx, &gc, "%s", label);
 		free(label);