From b7ff5259f518aa1452a3b175c8259b25c979c6a9 Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Wed, 8 Jul 2026 08:54:24 +0100 Subject: [PATCH] Refactor, clean up, remove state from layout_cell and move to a temp structure while parsing. --- layout-custom.c | 443 ++++++++++++++++++++++++++++++++++-------------- layout.c | 2 - tmux.h | 5 - 3 files changed, 316 insertions(+), 134 deletions(-) diff --git a/layout-custom.c b/layout-custom.c index a284b5fe4..ed115b486 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -95,15 +95,36 @@ struct layout_parse_ctx { u_int cells; }; +TAILQ_HEAD(parsed_layout_cells, parsed_layout_cell); + +struct parsed_layout_cell { + enum layout_type type; + int flags; +#define PARSED_CELL_FLOATING 0x1 +#define PARSED_CELL_HIDDEN 0x2 +#define PARSED_CELL_ZOOMED 0x4 +#define PARSED_CELL_X_RELATIVE 0x8 +#define PARSED_CELL_Y_RELATIVE 0x10 + u_int pane_id; + u_int z_index; + struct layout_geometry g; + struct layout_geometry fg; + struct parsed_layout_cell *parent; + struct parsed_layout_cells cells; + struct layout_cell *layout_cell; + TAILQ_ENTRY(parsed_layout_cell) entry; +}; + struct layout_prepared { - struct layout_cell *root; - struct layout_cell *zoomed; + struct parsed_layout_cell *root; + struct parsed_layout_cell *zoomed; enum layout_format format; u_int ncells; int pane_ids; }; -static struct layout_cell *layout_find_bottomright(struct layout_cell *); +static struct parsed_layout_cell *layout_find_bottomright( + struct parsed_layout_cell *); static u_short layout_checksum(const char *, const char *); static int layout_append(struct window *, struct layout_cell *, char *, size_t); @@ -111,29 +132,169 @@ static int layout_append_legacy(struct layout_cell *, char *, size_t); static int layout_append_geometry(char *, size_t, u_int, u_int, int, int); -static int layout_check(struct layout_cell *); +static int layout_check(struct parsed_layout_cell *); static int layout_check_geometry(u_int, u_int, int, int); static int layout_parse_char(struct layout_parse_ctx *, char); static int layout_parse_version(struct layout_parse_ctx *); static int layout_construct(struct layout_parse_ctx *, - struct layout_cell *, struct layout_cell **); -static void layout_assign(struct window *, struct window_pane **, - struct layout_cell *, int); -static struct layout_cell *layout_find_zindex(struct layout_cell *, + struct parsed_layout_cell *, + struct parsed_layout_cell **); +static struct parsed_layout_cell *layout_find_zindex( + struct parsed_layout_cell *, u_int); -static void layout_compact_zindexes(struct layout_cell *, +static void layout_compact_zindexes( + struct parsed_layout_cell *, u_int); /* Find the bottom-right cell. */ -static struct layout_cell * -layout_find_bottomright(struct layout_cell *lc) +static struct parsed_layout_cell * +layout_find_bottomright(struct parsed_layout_cell *lc) { if (lc->type == LAYOUT_WINDOWPANE) return (lc); - lc = TAILQ_LAST(&lc->cells, layout_cells); + lc = TAILQ_LAST(&lc->cells, parsed_layout_cells); return (layout_find_bottomright(lc)); } +/* Create a cell in the temporary parsed layout tree. */ +static struct parsed_layout_cell * +layout_create_parsed_cell(struct parsed_layout_cell *parent) +{ + struct parsed_layout_cell *lc; + + lc = xcalloc(1, sizeof *lc); + lc->type = LAYOUT_WINDOWPANE; + lc->pane_id = UINT_MAX; + lc->z_index = UINT_MAX; + lc->parent = parent; + lc->g.sx = lc->g.sy = UINT_MAX; + lc->g.xoff = lc->g.yoff = INT_MAX; + lc->fg.sx = lc->fg.sy = UINT_MAX; + lc->fg.xoff = lc->fg.yoff = INT_MAX; + TAILQ_INIT(&lc->cells); + return (lc); +} + +/* Free a temporary parsed layout tree. */ +static void +layout_free_parsed_cell(struct parsed_layout_cell *lc) +{ + struct parsed_layout_cell *lcchild; + + if (lc == NULL) + return; + while ((lcchild = TAILQ_FIRST(&lc->cells)) != NULL) { + TAILQ_REMOVE(&lc->cells, lcchild, entry); + layout_free_parsed_cell(lcchild); + } + free(lc); +} + +/* Return whether a parsed subtree contains a tiled pane. */ +static int +layout_parsed_has_tiled(struct parsed_layout_cell *lc) +{ + struct parsed_layout_cell *lcchild; + + if (lc->type == LAYOUT_WINDOWPANE) + return ((lc->flags & PARSED_CELL_FLOATING) == 0); + TAILQ_FOREACH(lcchild, &lc->cells, entry) { + if (layout_parsed_has_tiled(lcchild)) + return (1); + } + return (0); +} + +/* Count pane cells in a parsed tree. */ +static u_int +layout_count_parsed_cells(struct parsed_layout_cell *lc) +{ + struct parsed_layout_cell *lcchild; + u_int count = 0; + + if (lc->type == LAYOUT_WINDOWPANE) + return (1); + TAILQ_FOREACH(lcchild, &lc->cells, entry) + count += layout_count_parsed_cells(lcchild); + return (count); +} + +/* Increase a parsed tiled subtree while preserving its geometry. */ +static void +layout_resize_parsed(struct parsed_layout_cell *lc, enum layout_type type, + u_int change) +{ + struct parsed_layout_cell *lcchild, *last = NULL; + + if (type == LAYOUT_LEFTRIGHT) + lc->g.sx += change; + else + lc->g.sy += change; + if (lc->type == LAYOUT_WINDOWPANE) + return; + if (lc->type == type) { + TAILQ_FOREACH(lcchild, &lc->cells, entry) { + if (layout_parsed_has_tiled(lcchild)) + last = lcchild; + } + if (last != NULL) + layout_resize_parsed(last, type, change); + } else { + TAILQ_FOREACH(lcchild, &lc->cells, entry) { + if (layout_parsed_has_tiled(lcchild)) + layout_resize_parsed(lcchild, type, change); + } + } +} + +/* Remove the bottom-right parsed pane cell and collapse an empty level. */ +static void +layout_destroy_parsed_cell(struct parsed_layout_cell *lc, + struct parsed_layout_cell **root) +{ + struct parsed_layout_cell *parent, *other, *only; + u_int change; + + parent = lc->parent; + if (parent == NULL) { + layout_free_parsed_cell(lc); + *root = NULL; + return; + } + if ((lc->flags & PARSED_CELL_FLOATING) == 0) { + other = TAILQ_PREV(lc, parsed_layout_cells, entry); + while (other != NULL && !layout_parsed_has_tiled(other)) + other = TAILQ_PREV(other, parsed_layout_cells, entry); + if (other == NULL) { + other = TAILQ_NEXT(lc, entry); + while (other != NULL && !layout_parsed_has_tiled(other)) + other = TAILQ_NEXT(other, entry); + } + if (other != NULL) { + change = (parent->type == LAYOUT_LEFTRIGHT ? + lc->g.sx : lc->g.sy) + 1; + layout_resize_parsed(other, parent->type, change); + } + } + TAILQ_REMOVE(&parent->cells, lc, entry); + layout_free_parsed_cell(lc); + + only = TAILQ_FIRST(&parent->cells); + if (only != NULL && TAILQ_NEXT(only, entry) == NULL) { + TAILQ_REMOVE(&parent->cells, only, entry); + only->parent = parent->parent; + if (only->parent == NULL) { + if (layout_parsed_has_tiled(only)) { + only->g.xoff = 0; + only->g.yoff = 0; + } + *root = only; + } else + TAILQ_REPLACE(&only->parent->cells, parent, only, entry); + layout_free_parsed_cell(parent); + } +} + /* Calculate layout checksum. */ static u_short layout_checksum(const char *start, const char *end) @@ -362,9 +523,9 @@ layout_append(struct window *w, struct layout_cell *lc, char *buf, size_t len) /* Check tiled layout sizes fit, ignoring floating subtrees. */ static int -layout_check(struct layout_cell *lc) +layout_check(struct parsed_layout_cell *lc) { - struct layout_cell *lcchild; + struct parsed_layout_cell *lcchild; unsigned long long n = 0; u_int children = 0; @@ -373,7 +534,7 @@ layout_check(struct layout_cell *lc) return (1); case LAYOUT_LEFTRIGHT: TAILQ_FOREACH(lcchild, &lc->cells, entry) { - if (!layout_has_tiled(lcchild)) + if (!layout_parsed_has_tiled(lcchild)) continue; if (lcchild->g.sy != lc->g.sy || !layout_check(lcchild)) return (0); @@ -385,7 +546,7 @@ layout_check(struct layout_cell *lc) break; case LAYOUT_TOPBOTTOM: TAILQ_FOREACH(lcchild, &lc->cells, entry) { - if (!layout_has_tiled(lcchild)) + if (!layout_parsed_has_tiled(lcchild)) continue; if (lcchild->g.sx != lc->g.sx || !layout_check(lcchild)) return (0); @@ -414,9 +575,9 @@ layout_check_geometry(u_int sx, u_int sy, int xoff, int yoff) /* Correct the top cell size accepted from some older tmux versions. */ static int -layout_fix_legacy_root(struct layout_cell *root) +layout_fix_legacy_root(struct parsed_layout_cell *root) { - struct layout_cell *lcchild; + struct parsed_layout_cell *lcchild; unsigned long long sx = 0, sy = 0; if (root->type == LAYOUT_WINDOWPANE) @@ -656,10 +817,10 @@ layout_parse_version(struct layout_parse_ctx *ctx) /* Construct one cell, accepting an optional checksum before nested cells. */ static int -layout_construct(struct layout_parse_ctx *ctx, struct layout_cell *parent, - struct layout_cell **lcp) +layout_construct(struct layout_parse_ctx *ctx, struct parsed_layout_cell *parent, + struct parsed_layout_cell **lcp) { - struct layout_cell *lc = NULL, *lcchild; + struct parsed_layout_cell *lc = NULL, *lcchild; const char *body, *saved; u_int sx, sy, id, z; u_short csum = 0; @@ -690,12 +851,15 @@ layout_construct(struct layout_parse_ctx *ctx, struct layout_cell *parent, &xrelative, &yrelative) != 0) goto fail; - lc = layout_create_cell(parent); - layout_set_size(lc, sx, sy, xoff, yoff); + lc = layout_create_parsed_cell(parent); + lc->g.sx = sx; + lc->g.sy = sy; + lc->g.xoff = xoff; + lc->g.yoff = yoff; if (xrelative) - lc->flags |= LAYOUT_CELL_X_RELATIVE; + lc->flags |= PARSED_CELL_X_RELATIVE; if (yrelative) - lc->flags |= LAYOUT_CELL_Y_RELATIVE; + lc->flags |= PARSED_CELL_Y_RELATIVE; if (!is_pane && (xrelative || yrelative)) goto fail; layout_skip_space(ctx); @@ -715,15 +879,15 @@ layout_construct(struct layout_parse_ctx *ctx, struct layout_cell *parent, if (*ctx->ptr == 'f') { if (have_flags[0]++) goto fail; - lc->flags |= LAYOUT_CELL_FLOATING; + lc->flags |= PARSED_CELL_FLOATING; } else if (*ctx->ptr == 'h') { if (have_flags[1]++) goto fail; - lc->flags |= LAYOUT_CELL_HIDDEN; + lc->flags |= PARSED_CELL_HIDDEN; } else if (*ctx->ptr == 'z') { if (have_flags[2]++) goto fail; - lc->flags |= LAYOUT_CELL_ZOOMED; + lc->flags |= PARSED_CELL_ZOOMED; } else break; ctx->ptr++; @@ -731,11 +895,11 @@ layout_construct(struct layout_parse_ctx *ctx, struct layout_cell *parent, if (have_flags[1] && have_flags[2]) goto fail; } - if ((lc->flags & (LAYOUT_CELL_X_RELATIVE| - LAYOUT_CELL_Y_RELATIVE)) && - (lc->flags & LAYOUT_CELL_FLOATING) == 0) + if ((lc->flags & (PARSED_CELL_X_RELATIVE| + PARSED_CELL_Y_RELATIVE)) && + (lc->flags & PARSED_CELL_FLOATING) == 0) goto fail; - if (lc->flags & LAYOUT_CELL_HIDDEN) { + if (lc->flags & PARSED_CELL_HIDDEN) { lc->fg.sx = lc->g.sx; lc->fg.sy = lc->g.sy; lc->fg.xoff = lc->g.xoff; @@ -796,15 +960,15 @@ layout_construct(struct layout_parse_ctx *ctx, struct layout_cell *parent, fail: ctx->depth--; - layout_free_cell(lc, 0); + layout_free_parsed_cell(lc); return (-1); } /* Resolve right and bottom offsets against the complete window geometry. */ static int -layout_resolve_relative(struct layout_cell *lc, u_int sx, u_int sy) +layout_resolve_relative(struct parsed_layout_cell *lc, u_int sx, u_int sy) { - struct layout_cell *lcchild; + struct parsed_layout_cell *lcchild; long long resolved; if (lc->type != LAYOUT_WINDOWPANE) { @@ -814,21 +978,21 @@ layout_resolve_relative(struct layout_cell *lc, u_int sx, u_int sy) } return (0); } - if (lc->flags & LAYOUT_CELL_X_RELATIVE) { + if (lc->flags & PARSED_CELL_X_RELATIVE) { resolved = (long long)sx - lc->g.sx - lc->g.xoff; if (resolved < INT_MIN || resolved > INT_MAX) return (-1); lc->g.xoff = resolved; - lc->flags &= ~LAYOUT_CELL_X_RELATIVE; + lc->flags &= ~PARSED_CELL_X_RELATIVE; } - if (lc->flags & LAYOUT_CELL_Y_RELATIVE) { + if (lc->flags & PARSED_CELL_Y_RELATIVE) { resolved = (long long)sy - lc->g.sy - lc->g.yoff; if (resolved < INT_MIN || resolved > INT_MAX) return (-1); lc->g.yoff = resolved; - lc->flags &= ~LAYOUT_CELL_Y_RELATIVE; + lc->flags &= ~PARSED_CELL_Y_RELATIVE; } - if (lc->flags & LAYOUT_CELL_HIDDEN) { + if (lc->flags & PARSED_CELL_HIDDEN) { lc->fg.sx = lc->g.sx; lc->fg.sy = lc->g.sy; lc->fg.xoff = lc->g.xoff; @@ -841,10 +1005,10 @@ layout_resolve_relative(struct layout_cell *lc, u_int sx, u_int sy) /* Count zoomed cells and validate z-indexes and floating ordering. */ static int -layout_validate_new(struct layout_cell *root, u_int ncells, - struct layout_cell **zoomed) +layout_validate_new(struct parsed_layout_cell *root, u_int ncells, + struct parsed_layout_cell **zoomed) { - struct layout_cell *lc; + struct parsed_layout_cell *lc; u_int z; int seen_tiled = 0; @@ -853,12 +1017,12 @@ layout_validate_new(struct layout_cell *root, u_int ncells, lc = layout_find_zindex(root, z); if (lc == NULL) return (-1); - if (lc->flags & LAYOUT_CELL_FLOATING) { + if (lc->flags & PARSED_CELL_FLOATING) { if (seen_tiled) return (-1); } else seen_tiled = 1; - if (lc->flags & LAYOUT_CELL_ZOOMED) { + if (lc->flags & PARSED_CELL_ZOOMED) { if (*zoomed != NULL) return (-1); *zoomed = lc; @@ -868,10 +1032,10 @@ layout_validate_new(struct layout_cell *root, u_int ncells, } /* Find a leaf with a given parsed z-index. */ -static struct layout_cell * -layout_find_zindex(struct layout_cell *lc, u_int z) +static struct parsed_layout_cell * +layout_find_zindex(struct parsed_layout_cell *lc, u_int z) { - struct layout_cell *lcchild, *found; + struct parsed_layout_cell *lcchild, *found; if (lc->type == LAYOUT_WINDOWPANE) return (lc->z_index == z ? lc : NULL); @@ -885,9 +1049,9 @@ layout_find_zindex(struct layout_cell *lc, u_int z) /* Compact z-indexes while preserving the order of the remaining cells. */ static void -layout_compact_zindexes(struct layout_cell *root, u_int old_ncells) +layout_compact_zindexes(struct parsed_layout_cell *root, u_int old_ncells) { - struct layout_cell *lc; + struct parsed_layout_cell *lc; u_int old_z, new_z = 0; for (old_z = 0; old_z < old_ncells; old_z++) { @@ -899,9 +1063,9 @@ layout_compact_zindexes(struct layout_cell *root, u_int old_ncells) /* Count leaves containing a pane ID. */ static u_int -layout_count_pane_id(struct layout_cell *lc, u_int pane_id) +layout_count_pane_id(struct parsed_layout_cell *lc, u_int pane_id) { - struct layout_cell *lcchild; + struct parsed_layout_cell *lcchild; u_int count = 0; if (lc->type == LAYOUT_WINDOWPANE) @@ -914,9 +1078,9 @@ layout_count_pane_id(struct layout_cell *lc, u_int pane_id) /* Return whether every parsed pane ID is unique. */ static int -layout_pane_ids_unique(struct layout_cell *root, struct layout_cell *lc) +layout_pane_ids_unique(struct parsed_layout_cell *root, struct parsed_layout_cell *lc) { - struct layout_cell *lcchild; + struct parsed_layout_cell *lcchild; if (lc->type == LAYOUT_WINDOWPANE) return (layout_count_pane_id(root, lc->pane_id) == 1); @@ -929,9 +1093,9 @@ layout_pane_ids_unique(struct layout_cell *root, struct layout_cell *lc) /* Count parsed pane IDs belonging to the target window. */ static u_int -layout_pane_ids_matching(struct window *w, struct layout_cell *lc) +layout_pane_ids_matching(struct window *w, struct parsed_layout_cell *lc) { - struct layout_cell *lcchild; + struct parsed_layout_cell *lcchild; struct window_pane *wp; u_int matches = 0; @@ -946,7 +1110,7 @@ layout_pane_ids_matching(struct window *w, struct layout_cell *lc) /* Return 1 to assign by ID, 0 by tree order, or -1 for ambiguous IDs. */ static int -layout_pane_ids_status(struct window *w, struct layout_cell *root, +layout_pane_ids_status(struct window *w, struct parsed_layout_cell *root, u_int ncells) { u_int matches; @@ -964,8 +1128,8 @@ struct layout_prepared * layout_prepare(struct window *w, const char *layout, char **cause) { struct layout_parse_ctx ctx; - struct layout_cell *lcchild, *root = NULL, *zoomed = NULL; - struct layout_prepared *prepared; + struct parsed_layout_cell *lcchild, *root = NULL, *zoomed = NULL; + struct layout_prepared *parsed; const char *body; u_int npanes, ncells, old_ncells; u_short csum; @@ -993,31 +1157,31 @@ layout_prepare(struct window *w, const char *layout, char **cause) } if (layout_construct(&ctx, NULL, &root) != 0) { *cause = xstrdup("invalid layout"); - layout_free_cell(root, 0); + layout_free_parsed_cell(root); return (NULL); } layout_skip_space(&ctx); if (ctx.ptr != ctx.end || root == NULL) { *cause = xstrdup("invalid layout"); - layout_free_cell(root, 0); + layout_free_parsed_cell(root); return (NULL); } if ((version == 1 && ctx.format != LAYOUT_FORMAT) || (version == 0 && ctx.format == LAYOUT_FORMAT)) { *cause = xstrdup("invalid layout version"); - layout_free_cell(root, 0); + layout_free_parsed_cell(root); return (NULL); } if (layout_resolve_relative(root, root->type == LAYOUT_WINDOWPANE ? w->sx : root->g.sx, root->type == LAYOUT_WINDOWPANE ? w->sy : root->g.sy) != 0) { *cause = xstrdup("invalid layout"); - layout_free_cell(root, 0); + layout_free_parsed_cell(root); return (NULL); } npanes = window_count_panes(w, 1); - ncells = layout_count_cells(root); + ncells = layout_count_parsed_cells(root); if (ctx.format == LAYOUT_FORMAT) { old_ncells = ncells; if (npanes > ncells || @@ -1033,7 +1197,7 @@ layout_prepare(struct window *w, const char *layout, char **cause) if (npanes < ncells) { while (npanes < ncells) { lcchild = layout_find_bottomright(root); - layout_destroy_cell(w, lcchild, &root); + layout_destroy_parsed_cell(lcchild, &root); ncells--; } layout_compact_zindexes(root, old_ncells); @@ -1056,7 +1220,7 @@ layout_prepare(struct window *w, const char *layout, char **cause) } else { while (npanes < ncells) { lcchild = layout_find_bottomright(root); - layout_destroy_cell(w, lcchild, &root); + layout_destroy_parsed_cell(lcchild, &root); ncells--; } if (npanes > ncells) { @@ -1075,53 +1239,109 @@ layout_prepare(struct window *w, const char *layout, char **cause) goto fail; } - prepared = xcalloc(1, sizeof *prepared); - prepared->root = root; - prepared->zoomed = zoomed; - prepared->format = ctx.format; - prepared->ncells = ncells; - prepared->pane_ids = pane_ids; - return (prepared); + parsed = xcalloc(1, sizeof *parsed); + parsed->root = root; + parsed->zoomed = zoomed; + parsed->format = ctx.format; + parsed->ncells = ncells; + parsed->pane_ids = pane_ids; + return (parsed); fail: - layout_free_cell(root, 0); + layout_free_parsed_cell(root); return (NULL); } -/* Free a prepared layout without applying it. */ +/* Free a parsed layout without applying it. */ void -layout_free_prepared(struct layout_prepared *prepared) +layout_free_prepared(struct layout_prepared *parsed) { - if (prepared == NULL) + if (parsed == NULL) return; - layout_free_cell(prepared->root, 0); - free(prepared); + layout_free_parsed_cell(parsed->root); + free(parsed); } -/* Apply and free a prepared layout. This cannot fail. */ -void -layout_apply_prepared(struct window *w, struct layout_prepared *prepared) +/* Convert one validated parsed cell to a runtime layout cell. */ +static struct layout_cell * +layout_build_cell(struct parsed_layout_cell *parsed, struct layout_cell *parent, + struct window_pane **wp, int by_id) { - struct layout_cell *lcchild, *root = prepared->root; - struct window_pane *wp; - u_int z; + struct parsed_layout_cell *parsed_child; + struct layout_cell *lc, *lcchild; + struct window_pane *new_wp; - prepared->root = NULL; + lc = layout_create_cell(parent); + parsed->layout_cell = lc; + layout_set_size(lc, parsed->g.sx, parsed->g.sy, parsed->g.xoff, + parsed->g.yoff); + if (parsed->flags & PARSED_CELL_FLOATING) + lc->flags |= LAYOUT_CELL_FLOATING; + if (parsed->flags & PARSED_CELL_HIDDEN) + lc->flags |= LAYOUT_CELL_HIDDEN; + lc->fg = parsed->fg; + + if (parsed->type == LAYOUT_WINDOWPANE) { + if (by_id) + new_wp = window_pane_find_by_id(parsed->pane_id); + else { + new_wp = *wp; + *wp = TAILQ_NEXT(*wp, entry); + } + lc->wp = new_wp; + return (lc); + } + + lc->type = parsed->type; + TAILQ_FOREACH(parsed_child, &parsed->cells, entry) { + lcchild = layout_build_cell(parsed_child, lc, wp, by_id); + TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry); + } + return (lc); +} + +/* Link panes after the old runtime tree has been freed. */ +static void +layout_link_cells(struct layout_cell *lc) +{ + struct layout_cell *lcchild; + + if (lc->type == LAYOUT_WINDOWPANE) { + lc->wp->layout_cell = lc; + return; + } + TAILQ_FOREACH(lcchild, &lc->cells, entry) + layout_link_cells(lcchild); +} + +/* Apply and free a parsed layout. This cannot fail. */ +void +layout_apply_prepared(struct window *w, struct layout_prepared *parsed) +{ + struct parsed_layout_cell *cell, *parsed_root = parsed->root; + struct layout_cell *root; + struct window_pane *wp, *zoomed = NULL; + u_int z; + + wp = TAILQ_FIRST(&w->panes); + root = layout_build_cell(parsed_root, NULL, &wp, parsed->pane_ids); + if (parsed->zoomed != NULL) + zoomed = parsed->zoomed->layout_cell->wp; /* The layout was fully validated before the existing layout is changed. */ layout_free_cell(w->layout_root, 0); w->layout_root = root; - wp = TAILQ_FIRST(&w->panes); - layout_assign(w, &wp, root, prepared->pane_ids); + layout_link_cells(root); while (!TAILQ_EMPTY(&w->z_index)) { wp = TAILQ_FIRST(&w->z_index); TAILQ_REMOVE(&w->z_index, wp, zentry); } - if (prepared->format == LAYOUT_FORMAT) { - for (z = 0; z < prepared->ncells; z++) { - lcchild = layout_find_zindex(root, z); - TAILQ_INSERT_TAIL(&w->z_index, lcchild->wp, zentry); + if (parsed->format == LAYOUT_FORMAT) { + for (z = 0; z < parsed->ncells; z++) { + cell = layout_find_zindex(parsed_root, z); + TAILQ_INSERT_TAIL(&w->z_index, + cell->layout_cell->wp, zentry); } } else layout_fix_zindexes(w, root); @@ -1132,39 +1352,8 @@ layout_apply_prepared(struct window *w, struct layout_prepared *prepared) layout_fix_panes(w, NULL); layout_print_cell(root, __func__, 0); - if (prepared->zoomed != NULL) { - prepared->zoomed->flags &= ~LAYOUT_CELL_ZOOMED; - window_zoom(prepared->zoomed->wp); - } - free(prepared); -} - -/* Assign panes to cells in tree order. */ -static void -layout_assign(struct window *w, struct window_pane **wp, - struct layout_cell *lc, int by_id) -{ - struct layout_cell *lcchild; - struct window_pane *new_wp; - - if (lc == NULL) - return; - switch (lc->type) { - case LAYOUT_WINDOWPANE: - if (by_id) { - new_wp = window_pane_find_by_id(lc->pane_id); - if (new_wp == NULL || new_wp->window != w) - return; - } else { - new_wp = *wp; - *wp = TAILQ_NEXT(*wp, entry); - } - layout_make_leaf(lc, new_wp); - return; - case LAYOUT_LEFTRIGHT: - case LAYOUT_TOPBOTTOM: - TAILQ_FOREACH(lcchild, &lc->cells, entry) - layout_assign(w, wp, lcchild, by_id); - return; - } + layout_free_parsed_cell(parsed_root); + free(parsed); + if (zoomed != NULL) + window_zoom(zoomed); } diff --git a/layout.c b/layout.c index 1f78c446d..256c66665 100644 --- a/layout.c +++ b/layout.c @@ -74,8 +74,6 @@ layout_create_cell(struct layout_cell *lcparent) lc = xcalloc(1, sizeof *lc); lc->type = LAYOUT_WINDOWPANE; - lc->z_index = UINT_MAX; - lc->pane_id = UINT_MAX; lc->parent = lcparent; TAILQ_INIT(&lc->cells); diff --git a/tmux.h b/tmux.h index b1504bace..c3c65afaf 100644 --- a/tmux.h +++ b/tmux.h @@ -1523,11 +1523,6 @@ struct layout_cell { int flags; #define LAYOUT_CELL_FLOATING 0x1 #define LAYOUT_CELL_HIDDEN 0x2 /* hidden in a serialized layout */ -#define LAYOUT_CELL_ZOOMED 0x4 /* only while parsing a layout */ -#define LAYOUT_CELL_X_RELATIVE 0x8 /* only while parsing a layout */ -#define LAYOUT_CELL_Y_RELATIVE 0x10 /* only while parsing a layout */ - u_int z_index; /* only while parsing a layout */ - u_int pane_id; /* only while parsing a layout */ struct layout_cell *parent;