diff options
Diffstat (limited to 'usr.bin/tmux/layout-manual.c')
-rw-r--r-- | usr.bin/tmux/layout-manual.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/usr.bin/tmux/layout-manual.c b/usr.bin/tmux/layout-manual.c new file mode 100644 index 00000000000..66d472d620b --- /dev/null +++ b/usr.bin/tmux/layout-manual.c @@ -0,0 +1,183 @@ +/* $OpenBSD: layout-manual.c,v 1.1 2009/06/01 22:58:49 nicm Exp $ */ + +/* + * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.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 "tmux.h" + +void layout_manual_v_update_offsets(struct window *); + +void +layout_manual_v_refresh(struct window *w, unused int active_only) +{ + struct window_pane *wp; + u_int npanes, canfit, total; + int left; + + if (active_only) + return; + + if (TAILQ_EMPTY(&w->panes)) + return; + + /* Clear hidden flags. */ + TAILQ_FOREACH(wp, &w->panes, entry) + wp->flags &= ~PANE_HIDDEN; + + /* Check the new size. */ + npanes = window_count_panes(w); + if (w->sy <= PANE_MINIMUM * npanes) { + /* How many can we fit? */ + canfit = w->sy / PANE_MINIMUM; + if (canfit == 0) { + /* None. Just use this size for the first. */ + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp == TAILQ_FIRST(&w->panes)) + wp->sy = w->sy; + else + wp->flags |= PANE_HIDDEN; + } + } else { + /* >=1, set minimum for them all. */ + TAILQ_FOREACH(wp, &w->panes, entry) { + if (canfit-- > 0) + wp->sy = PANE_MINIMUM - 1; + else + wp->flags |= PANE_HIDDEN; + } + /* And increase the first by the rest. */ + TAILQ_FIRST(&w->panes)->sy += 1 + w->sy % PANE_MINIMUM; + } + } else { + /* In theory they will all fit. Find the current total. */ + total = 0; + TAILQ_FOREACH(wp, &w->panes, entry) + total += wp->sy; + total += npanes - 1; + + /* Growing or shrinking? */ + left = w->sy - total; + if (left > 0) { + /* Growing. Expand evenly. */ + while (left > 0) { + TAILQ_FOREACH(wp, &w->panes, entry) { + wp->sy++; + if (--left == 0) + break; + } + } + } else { + /* Shrinking. Reduce evenly down to minimum. */ + while (left < 0) { + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp->sy <= PANE_MINIMUM - 1) + continue; + wp->sy--; + if (++left == 0) + break; + } + } + } + } + + /* Now do the resize. */ + TAILQ_FOREACH(wp, &w->panes, entry) { + wp->sy--; + window_pane_resize(wp, w->sx, wp->sy + 1); + } + + /* Fill in the offsets. */ + layout_manual_v_update_offsets(w); + + /* Switch the active window if necessary. */ + window_set_active_pane(w, w->active); +} + +void +layout_manual_v_resize(struct window_pane *wp, int adjust) +{ + struct window *w = wp->window; + struct window_pane *wq; + + if (adjust > 0) { + /* + * If this is not the last pane, keep trying to increase size + * and remove it from the next panes. If it is the last, do + * so on the previous pane. + */ + if (TAILQ_NEXT(wp, entry) == NULL) { + if (wp == TAILQ_FIRST(&w->panes)) { + /* Only one pane. */ + return; + } + wp = TAILQ_PREV(wp, window_panes, entry); + } + while (adjust-- > 0) { + wq = wp; + while ((wq = TAILQ_NEXT(wq, entry)) != NULL) { + if (wq->sy <= PANE_MINIMUM) + continue; + window_pane_resize(wq, wq->sx, wq->sy - 1); + break; + } + if (wq == NULL) + break; + window_pane_resize(wp, wp->sx, wp->sy + 1); + } + } else { + adjust = -adjust; + /* + * If this is not the last pane, keep trying to reduce size + * and add to the following pane. If it is the last, do so on + * the previous pane. + */ + wq = TAILQ_NEXT(wp, entry); + if (wq == NULL) { + if (wp == TAILQ_FIRST(&w->panes)) { + /* Only one pane. */ + return; + } + wq = wp; + wp = TAILQ_PREV(wq, window_panes, entry); + } + while (adjust-- > 0) { + if (wp->sy <= PANE_MINIMUM) + break; + window_pane_resize(wq, wq->sx, wq->sy + 1); + window_pane_resize(wp, wp->sx, wp->sy - 1); + } + } + + layout_manual_v_update_offsets(w); +} + +void +layout_manual_v_update_offsets(struct window *w) +{ + struct window_pane *wp; + u_int yoff; + + yoff = 0; + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp->flags & PANE_HIDDEN) + continue; + wp->xoff = 0; + wp->yoff = yoff; + yoff += wp->sy + 1; + } +} |