diff --git a/cmd-split-window.c b/cmd-split-window.c index a8406170..4527a750 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -70,63 +70,6 @@ const struct cmd_entry cmd_split_window_entry = { .exec = cmd_split_window_exec }; -static struct layout_cell * -cmd_split_window_get_floating_cell(struct cmdq_item *item, struct args *args, - struct window *w, struct window_pane *wp) -{ - struct layout_cell *lc = NULL; - char *cause = NULL; - u_int x, y, sx, sy; - - if (window_pane_floating_geometry(w, wp, &x, &y, &sx, &sy, item, args, - &cause) != 0) { - cmdq_error(item, "invalid floating pane geometry %s", cause); - free(cause); - return (NULL); - } - - /* - * Floating panes sit in layout cells which are not in the layout_root - * tree so we call it with parent == NULL. - */ - lc = layout_create_cell(NULL); - lc->xoff = x; - lc->yoff = y; - lc->sx = sx; - lc->sy = sy; - - return (lc); -} - -static struct layout_cell * -cmd_split_window_get_tiled_cell(struct cmdq_item *item, struct args *args, - struct window *w, struct window_pane *wp, int flags) -{ - enum layout_type type; - struct layout_cell *lc = NULL; - char *cause = NULL; - int size; - - if (window_pane_is_floating(wp)) { - cmdq_error(item, "can't split a floating pane"); - return (NULL); - } - - if (window_pane_tiled_geometry(w, wp, &size, &flags, &type, item, args, - &cause) != 0) { - cmdq_error(item, "invalid tiled geometry %s", cause); - free(cause); - return (NULL); - } - - window_push_zoom(wp->window, 1, args_has(args, 'Z')); - lc = layout_split_pane(wp, type, size, flags); - if (lc == NULL) - cmdq_error(item, "no space for new pane"); - - return (lc); -} - static enum cmd_retval cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) { @@ -162,11 +105,13 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) flags |= SPAWN_EMPTY; if (is_floating) - lc = cmd_split_window_get_floating_cell(item, args, w, wp); + lc = layout_get_floating_cell(item, args, w, wp, lc, &cause); else - lc = cmd_split_window_get_tiled_cell(item, args, w, wp, flags); - if (lc == NULL) + lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause); + if (cause != NULL) { + cmdq_error(item, "could not create cell: %s", cause); return (CMD_RETURN_ERROR); + } sc.item = item; sc.s = s; diff --git a/layout.c b/layout.c index b8c886e5..5cdb4134 100644 --- a/layout.c +++ b/layout.c @@ -1152,6 +1152,7 @@ layout_close_pane(struct window_pane *wp) notify_window("window-layout-changed", w); } +/* Spread out cells inside a parent cell. */ int layout_spread_cell(struct window *w, struct layout_cell *parent) { @@ -1180,6 +1181,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent) each = (size - (number - 1)) / number; if (each == 0) return (0); + /* * Remaining space after assigning that which can be evenly * distributed. @@ -1214,6 +1216,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent) return (changed); } +/* Spread out cells evenly. */ void layout_spread_out(struct window_pane *wp) { @@ -1232,3 +1235,140 @@ layout_spread_out(struct window_pane *wp) } } while ((parent = parent->parent) != NULL); } + +/* Get a new tiled cell. */ +struct layout_cell * +layout_get_tiled_cell(struct cmdq_item *item, struct args *args, + struct window *w, struct window_pane *wp, int flags, char **cause) +{ + struct layout_cell *lc; + enum layout_type type; + u_int curval; + int size = -1; + + if (window_pane_is_floating(wp)) { + *cause = xstrdup("can't split a floating pane"); + return (NULL); + } + + type = LAYOUT_TOPBOTTOM; + if (args_has(args, 'h')) + type = LAYOUT_LEFTRIGHT; + + if (args_has(args, 'l') || args_has(args, 'p')) { + if (args_has(args, 'f')) { + if (type == LAYOUT_TOPBOTTOM) + curval = w->sy; + else + curval = w->sx; + } else { + if (type == LAYOUT_TOPBOTTOM) + curval = wp->sy; + else + curval = wp->sx; + } + } + + if (args_has(args, 'l')) { + size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval, + item, cause); + } else if (args_has(args, 'p')) { + size = args_strtonum_and_expand(args, 'p', 0, 100, item, + cause); + if (*cause == NULL) + size = curval * size / 100; + } + if (*cause != NULL) { + *cause = xstrdup("invalid tiled geometry"); + return (NULL); + } + + if (args_has(args, 'b')) + flags |= SPAWN_BEFORE; + if (args_has(args, 'f')) + flags |= SPAWN_FULLSIZE; + + window_push_zoom(wp->window, 1, args_has(args, 'Z')); + lc = layout_split_pane(wp, type, size, flags); + if (lc == NULL) + *cause = xstrdup("no space for a new pane"); + + return (lc); +} + +/* Get a new floating cell. */ +struct layout_cell * +layout_get_floating_cell(struct cmdq_item *item, struct args *args, + struct window *w, __unused struct window_pane *wp, struct layout_cell *lc, + char **cause) +{ + u_int sx, sy, ox, oy; + int new = 0; + + if (lc == NULL) { + lc = layout_create_cell(NULL); + new = 1; + } + + sx = lc->sx; sy = lc->sy; + ox = lc->xoff; oy = lc->yoff; + + if (args_has(args, 'x')) { + sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx, + item, cause); + if (*cause != NULL) + goto error; + } + if (args_has(args, 'y')) { + sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy, + item, cause); + if (*cause != NULL) + goto error; + } + if (args_has(args, 'X')) { + ox = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx, + item, cause); + if (*cause != NULL) + goto error; + } + if (args_has(args, 'Y')) { + oy = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy, + item, cause); + if (*cause != NULL) + goto error; + } + + if (sx == UINT_MAX) + sx = w->sx / 2; + if (sy == UINT_MAX) + sy = w->sy / 4; + if (ox == INT_MAX) { + if (w->last_new_pane_x == 0) + ox = 4; + else { + ox = w->last_new_pane_x + 4; + if (w->last_new_pane_x > w->sx) + ox = 4; + } + w->last_new_pane_x = ox; + } + if (oy == INT_MAX) { + if (w->last_new_pane_y == 0) + oy = 2; + else { + oy = w->last_new_pane_y + 2; + if (w->last_new_pane_y > w->sy) + oy = 2; + } + w->last_new_pane_y = oy; + } + layout_set_size(lc, sx, sy, ox, oy); + lc->flags |= LAYOUT_CELL_FLOATING; + + return (lc); + +error: + if (new) + layout_destroy_cell(w, lc, &w->layout_root); + return (NULL); +} diff --git a/tmux.h b/tmux.h index 82c2e6d4..612d7008 100644 --- a/tmux.h +++ b/tmux.h @@ -3451,12 +3451,6 @@ void window_pane_send_theme_update(struct window_pane *); struct style_range *window_pane_border_status_get_range(struct window_pane *, u_int, u_int); int window_pane_is_floating(struct window_pane *); -int window_pane_tiled_geometry(struct window *, - struct window_pane *, int *, int *, enum layout_type *, - struct cmdq_item *, struct args *, char **); -int window_pane_floating_geometry(struct window *, - struct window_pane *, u_int *, u_int *, u_int *, u_int *, - struct cmdq_item *, struct args *, char **); /* layout.c */ u_int layout_count_cells(struct layout_cell *); @@ -3490,6 +3484,11 @@ struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type, void layout_close_pane(struct window_pane *); int layout_spread_cell(struct window *, struct layout_cell *); void layout_spread_out(struct window_pane *); +struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *, + struct window *, struct window_pane *, struct layout_cell *, + char **); +struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *, + struct window *, struct window_pane *, int, char **); /* layout-custom.c */ char *layout_dump(struct window *, struct layout_cell *); diff --git a/window.c b/window.c index db526d27..c0d9078c 100644 --- a/window.c +++ b/window.c @@ -2083,124 +2083,6 @@ window_pane_border_status_get_range(struct window_pane *wp, u_int x, u_int y) return (style_ranges_get_range(srs, x - wp->xoff - 2)); } -/* Work out geometry for tiled panes. */ -int -window_pane_tiled_geometry(struct window *w, struct window_pane *wp, - int *out_size, int *out_flags, enum layout_type *out_type, - struct cmdq_item *item, struct args *args, char **cause) -{ - int size = -1, flags = *out_flags; - enum layout_type type; - u_int curval = 0; - - type = LAYOUT_TOPBOTTOM; - if (args_has(args, 'h')) - type = LAYOUT_LEFTRIGHT; - - if (args_has(args, 'l') || args_has(args, 'p')) { - if (args_has(args, 'f')) { - if (type == LAYOUT_TOPBOTTOM) - curval = w->sy; - else - curval = w->sx; - } else { - if (type == LAYOUT_TOPBOTTOM) - curval = wp->sy; - else - curval = wp->sx; - } - } - - if (args_has(args, 'l')) { - size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval, - item, cause); - } else if (args_has(args, 'p')) { - size = args_strtonum_and_expand(args, 'p', 0, 100, item, - cause); - if (*cause == NULL) - size = curval * size / 100; - } - if (*cause != NULL) - return (-1); - - if (args_has(args, 'b')) - flags |= SPAWN_BEFORE; - if (args_has(args, 'f')) - flags |= SPAWN_FULLSIZE; - - *out_size = size; - *out_flags = flags; - *out_type = type; - return (0); -} - -/* Work out geometry for floating panes. */ -int -window_pane_floating_geometry(struct window *w, __unused struct window_pane *wp, - u_int *out_x, u_int *out_y, u_int *out_sx, u_int *out_sy, - struct cmdq_item *item, struct args *args, char **cause) -{ - u_int x, y, sx = w->sx / 2, sy = w->sy / 4; - - if (args_has(args, 'x')) { - sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx, - item, cause); - if (*cause != NULL) - return (-1); - } - if (args_has(args, 'y')) { - sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy, - item, cause); - if (*cause != NULL) - return (-1); - } - - if (args_has(args, 'X')) { - x = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx, - item, cause); - if (*cause != NULL) - return (-1); - } else { - if (w->last_new_pane_x == 0) - x = 4; - else { - x = w->last_new_pane_x + 4; - if (x + sx >= w->sx) { - w->last_new_pane_x = 0; - w->last_new_pane_y = 0; - x = 4; - y = 2; - } - } - w->last_new_pane_x = x; - } - if (args_has(args, 'Y')) { - y = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy, - item, cause); - if (*cause != NULL) - return (-1); - } else { - if (w->last_new_pane_y == 0) - y = 2; - else { - y = w->last_new_pane_y + 2; - if (y + sy >= w->sy) { - w->last_new_pane_x = 0; - w->last_new_pane_y = 0; - x = 4; - y = 2; - } - } - w->last_new_pane_y = y; - } - - *out_x = x; - *out_y = y; - *out_sx = sx; - *out_sy = sy; - return (0); -} - int window_pane_is_floating(struct window_pane *wp) {