/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
* Copyright (c) 2016 Stephen Kent <smkent@smkent.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* The window layout is a tree of cells each of which can be one of: a
* left-right container for a list of cells, a top-bottom container for a list
* of cells, or a container for a window pane.
*
* Each window has a pointer to the root of its layout tree (containing its
* panes), every pane has a pointer back to the cell containing it, and each
* cell a pointer to its parent cell.
*/
static u_int layout_resize_check(struct window *, struct layout_cell *,
enum layout_type);
static int layout_resize_pane_grow(struct window *, struct layout_cell *,
enum layout_type, int, int);
static int layout_resize_pane_shrink(struct window *, struct layout_cell *,
enum layout_type, int);
static u_int layout_new_pane_size(struct window *, u_int,
struct layout_cell *, enum layout_type, u_int, u_int,
u_int);
static int layout_set_size_check(struct window *, struct layout_cell *,
enum layout_type, int);
static void layout_resize_child_cells(struct window *,
struct layout_cell *);
struct layout_cell *
layout_create_cell(struct layout_cell *lcparent)
{
struct layout_cell *lc;
lc = xmalloc(sizeof *lc);
lc->type = LAYOUT_WINDOWPANE;
lc->parent = lcparent;
TAILQ_INIT(&lc->cells);
lc->sx = UINT_MAX;
lc->sy = UINT_MAX;
lc->xoff = UINT_MAX;
lc->yoff = UINT_MAX;
lc->wp = NULL;
return (lc);
}
void
layout_free_cell(struct layout_cell *lc)
{
struct layout_cell *lcchild;
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
while (!TAILQ_EMPTY(&lc->cells)) {
lcchild = TAILQ_FIRST(&lc->cells);
TAILQ_REMOVE(&lc->cells, lcchild, entry);
layout_free_cell(lcchild);
}
break;
case LAYOUT_WINDOWPANE:
if (lc->wp != NULL)
lc->wp->layout_cell = NULL;
break;
}
free(lc);
}
void
layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
{
struct layout_cell *lcchild;
const char *type;
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
type = "LEFTRIGHT";
break;
case LAYOUT_TOPBOTTOM:
type = "TOPBOTTOM";
break;
case LAYOUT_WINDOWPANE:
type = "WINDOWPANE";
break;
default:
type = "UNKNOWN";
break;
}
log_debug("%s:%*s%p type %s [parent %p] wp=%p [%u,%u %ux%u]", hdr, n,
" ", lc, type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx,
lc->sy);
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &lc->cells, entry)
layout_print_cell(lcchild, hdr, n + 1);
break;
case LAYOUT_WINDOWPANE:
break;
}
}
struct layout_cell *
layout_search_by_border(str