diff --git a/cmd-split-window.c b/cmd-split-window.c index f88b2f65..6b901254 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -36,8 +36,8 @@ enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *); const struct cmd_entry cmd_split_window_entry = { "split-window", "splitw", - "c:dF:l:hp:Pt:v", 0, -1, - "[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] " + "bc:dF:l:hp:Pt:v", 0, -1, + "[-bdhvP] [-c start-directory] [-F format] [-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]", 0, cmd_split_window_exec @@ -144,7 +144,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; - if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) { + lc = layout_split_pane(wp, type, size, args_has(args, 'b')); + if (lc == NULL) { cause = xstrdup("pane too small"); goto error; } diff --git a/grid-view.c b/grid-view.c index badabd56..a34c5a08 100644 --- a/grid-view.c +++ b/grid-view.c @@ -184,7 +184,9 @@ grid_view_insert_cells(struct grid *gd, u_int px, u_int py, u_int nx) px = grid_view_x(gd, px); py = grid_view_y(gd, py); - sx = grid_view_x(gd, gd->sx); + sx = grid_view_x(gd, gd->linedata[py].cellsize); + if (sx < px + nx) + sx = px + nx; if (px == sx - 1) grid_clear(gd, px, py, 1, 1); @@ -201,7 +203,9 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx) px = grid_view_x(gd, px); py = grid_view_y(gd, py); - sx = grid_view_x(gd, gd->sx); + sx = grid_view_x(gd, gd->linedata[py].cellsize); + if (sx < px + nx) + sx = px + nx; grid_move_cells(gd, px, px + nx, py, sx - px - nx); grid_clear(gd, sx - nx, py, px + nx - (sx - nx), 1); diff --git a/resize.c b/resize.c index 73a728fa..9ad73c81 100644 --- a/resize.c +++ b/resize.c @@ -50,7 +50,7 @@ recalculate_sizes(void) struct window *w; struct window_pane *wp; u_int i, j, ssx, ssy, has, limit; - int flag, has_status, is_zoomed; + int flag, has_status, is_zoomed, forced; RB_FOREACH(s, sessions, &sessions) { has_status = options_get_number(&s->options, "status"); @@ -116,18 +116,26 @@ recalculate_sizes(void) if (ssx == UINT_MAX || ssy == UINT_MAX) continue; + forced = 0; limit = options_get_number(&w->options, "force-width"); - if (limit >= PANE_MINIMUM && ssx > limit) + if (limit >= PANE_MINIMUM && ssx > limit) { ssx = limit; + forced |= WINDOW_FORCEWIDTH; + } limit = options_get_number(&w->options, "force-height"); - if (limit >= PANE_MINIMUM && ssy > limit) + if (limit >= PANE_MINIMUM && ssy > limit) { ssy = limit; + forced |= WINDOW_FORCEHEIGHT; + } if (w->sx == ssx && w->sy == ssy) continue; log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx, w->sy); + w->flags &= ~(WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT); + w->flags |= forced; + is_zoomed = w->flags & WINDOW_ZOOMED; if (is_zoomed) window_unzoom(w); diff --git a/screen-redraw.c b/screen-redraw.c index a7f713a5..ef9e539d 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -278,8 +278,37 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top) struct options *oo = &c->session->options; struct tty *tty = &c->tty; struct window_pane *wp; - struct grid_cell active_gc, other_gc; - u_int i, j, type; + struct grid_cell active_gc, other_gc, msg_gc; + u_int i, j, type, msgx = 0, msgy = 0; + int small, flags; + char msg[256]; + const char *tmp; + size_t msglen = 0; + + small = (tty->sy - status + top > w->sy) || (tty->sx > w->sx); + if (small) { + flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT); + if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT)) + tmp = "force-width, force-height"; + else if (flags == WINDOW_FORCEWIDTH) + tmp = "force-width"; + else if (flags == WINDOW_FORCEHEIGHT) + tmp = "force-height"; + else + tmp = "a smaller client"; + xsnprintf(msg, sizeof msg, "(size %ux%u from %s)", + w->sx, w->sy, tmp); + msglen = strlen(msg); + + if (tty->sy - 1 - status + top > w->sy && tty->sx >= msglen) { + msgx = tty->sx - msglen; + msgy = tty->sy - 1 - status + top; + } else if (tty->sx - w->sx > msglen) { + msgx = tty->sx - msglen; + msgy = tty->sy - 1 - status + top; + } else + small = 0; + } style_apply(&other_gc, oo, "pane-border-style"); style_apply(&active_gc, oo, "pane-active-border-style"); @@ -290,6 +319,9 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top) type = screen_redraw_check_cell(c, i, j, &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)) tty_attributes(tty, &active_gc); else @@ -298,6 +330,13 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top) tty_putc(tty, CELL_BORDERS[type]); } } + + if (small) { + memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc); + tty_attributes(tty, &msg_gc); + tty_cursor(tty, msgx, msgy); + tty_puts(tty, msg); + } } /* Draw the panes. */ diff --git a/tmux.1 b/tmux.1 index fb708ded..4a1eb54c 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1761,7 +1761,7 @@ is given and the selected window is already the current window, the command behaves like .Ic last-window . .It Xo Ic split-window -.Op Fl dhvP +.Op Fl bdhvP .Op Fl c Ar start-directory .Oo Fl l .Ar size | @@ -1785,6 +1785,10 @@ and .Fl p options specify the size of the new pane in lines (for vertical split) or in cells (for horizontal split), or as a percentage, respectively. +The +.Fl b +option causes the new pane to be created to the left of or above +.Ar target-pane . All other options have the same meaning as for the .Ic new-window command. diff --git a/tmux.h b/tmux.h index 57077a65..7c0a7b52 100644 --- a/tmux.h +++ b/tmux.h @@ -944,7 +944,9 @@ struct window { #define WINDOW_ACTIVITY 0x2 #define WINDOW_REDRAW 0x4 #define WINDOW_SILENCE 0x8 -#define WINDOW_ZOOMED 0x10 +#define WINDOW_ZOOMED 0x1000 +#define WINDOW_FORCEWIDTH 0x2000 +#define WINDOW_FORCEHEIGHT 0x4000 #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE) struct options options;