Annotation of src/usr.bin/tmux/layout.c, Revision 1.1
1.1 ! nicm 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
! 15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
! 16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/types.h>
! 20:
! 21: #include <string.h>
! 22:
! 23: #include "tmux.h"
! 24:
! 25: /*
! 26: * Each layout has two functions, _refresh to relayout the panes and _resize to
! 27: * resize a single pane.
! 28: *
! 29: * Second argument (int) to _refresh is 1 if the only change has been that the
! 30: * active pane has changed. If 0 then panes, active pane or both may have
! 31: * changed.
! 32: */
! 33:
! 34: void layout_active_only_refresh(struct window *, int);
! 35: void layout_even_h_refresh(struct window *, int);
! 36: void layout_even_v_refresh(struct window *, int);
! 37: void layout_main_h_refresh(struct window *, int);
! 38: void layout_main_v_refresh(struct window *, int);
! 39:
! 40: const struct {
! 41: const char *name;
! 42: void (*refresh)(struct window *, int);
! 43: void (*resize)(struct window_pane *, int);
! 44: } layouts[] = {
! 45: { "manual-vertical", layout_manual_v_refresh, layout_manual_v_resize },
! 46: { "active-only", layout_active_only_refresh, NULL },
! 47: { "even-horizontal", layout_even_h_refresh, NULL },
! 48: { "even-vertical", layout_even_v_refresh, NULL },
! 49: { "main-horizontal", layout_main_h_refresh, NULL },
! 50: { "main-vertical", layout_main_v_refresh, NULL },
! 51: };
! 52:
! 53: const char *
! 54: layout_name(struct window *w)
! 55: {
! 56: return (layouts[w->layout].name);
! 57: }
! 58:
! 59: int
! 60: layout_lookup(const char *name)
! 61: {
! 62: u_int i;
! 63: int matched = -1;
! 64:
! 65: for (i = 0; i < nitems(layouts); i++) {
! 66: if (strncmp(layouts[i].name, name, strlen(name)) == 0) {
! 67: if (matched != -1) /* ambiguous */
! 68: return (-1);
! 69: matched = i;
! 70: }
! 71: }
! 72:
! 73: return (matched);
! 74: }
! 75:
! 76: int
! 77: layout_select(struct window *w, u_int layout)
! 78: {
! 79: if (layout > nitems(layouts) - 1 || layout == w->layout)
! 80: return (-1);
! 81: w->layout = layout;
! 82:
! 83: layout_refresh(w, 0);
! 84: return (0);
! 85: }
! 86:
! 87: void
! 88: layout_next(struct window *w)
! 89: {
! 90: w->layout++;
! 91: if (w->layout > nitems(layouts) - 1)
! 92: w->layout = 0;
! 93: layout_refresh(w, 0);
! 94: }
! 95:
! 96: void
! 97: layout_previous(struct window *w)
! 98: {
! 99: if (w->layout == 0)
! 100: w->layout = nitems(layouts) - 1;
! 101: else
! 102: w->layout--;
! 103: layout_refresh(w, 0);
! 104: }
! 105:
! 106: void
! 107: layout_refresh(struct window *w, int active_only)
! 108: {
! 109: layouts[w->layout].refresh(w, active_only);
! 110: server_redraw_window(w);
! 111: }
! 112:
! 113: int
! 114: layout_resize(struct window_pane *wp, int adjust)
! 115: {
! 116: struct window *w = wp->window;
! 117:
! 118: if (layouts[w->layout].resize == NULL)
! 119: return (-1);
! 120: layouts[w->layout].resize(wp, adjust);
! 121: return (0);
! 122: }
! 123:
! 124: void
! 125: layout_active_only_refresh(struct window *w, unused int active_only)
! 126: {
! 127: struct window_pane *wp;
! 128:
! 129: TAILQ_FOREACH(wp, &w->panes, entry) {
! 130: if (wp == w->active) {
! 131: wp->flags &= ~PANE_HIDDEN;
! 132: wp->xoff = wp->yoff = 0;
! 133: window_pane_resize(wp, w->sx, w->sy);
! 134: } else
! 135: wp->flags |= PANE_HIDDEN;
! 136: }
! 137: }
! 138:
! 139: void
! 140: layout_even_h_refresh(struct window *w, int active_only)
! 141: {
! 142: struct window_pane *wp;
! 143: u_int i, n, width, xoff;
! 144:
! 145: if (active_only)
! 146: return;
! 147:
! 148: /* Get number of panes. */
! 149: n = window_count_panes(w);
! 150: if (n == 0)
! 151: return;
! 152:
! 153: /* How many can we fit? */
! 154: if (w->sx / n < PANE_MINIMUM) {
! 155: width = PANE_MINIMUM;
! 156: n = w->sx / PANE_MINIMUM;
! 157: } else
! 158: width = w->sx / n;
! 159:
! 160: /* Fit the panes. */
! 161: i = xoff = 0;
! 162: TAILQ_FOREACH(wp, &w->panes, entry) {
! 163: if (i > n) {
! 164: wp->flags |= PANE_HIDDEN;
! 165: continue;
! 166: }
! 167: wp->flags &= ~PANE_HIDDEN;
! 168:
! 169: wp->xoff = xoff;
! 170: wp->yoff = 0;
! 171: if (i != n - 1)
! 172: window_pane_resize(wp, width - 1, w->sy);
! 173: else
! 174: window_pane_resize(wp, width, w->sy);
! 175:
! 176: i++;
! 177: xoff += width;
! 178: }
! 179:
! 180: /* Any space left? */
! 181: while (xoff++ < w->sx) {
! 182: wp = TAILQ_LAST(&w->panes, window_panes);
! 183: window_pane_resize(wp, wp->sx + 1, wp->sy);
! 184: }
! 185: }
! 186:
! 187: void
! 188: layout_even_v_refresh(struct window *w, int active_only)
! 189: {
! 190: struct window_pane *wp;
! 191: u_int i, n, height, yoff;
! 192:
! 193: if (active_only)
! 194: return;
! 195:
! 196: /* Get number of panes. */
! 197: n = window_count_panes(w);
! 198: if (n == 0)
! 199: return;
! 200:
! 201: /* How many can we fit? */
! 202: if (w->sy / n < PANE_MINIMUM) {
! 203: height = PANE_MINIMUM;
! 204: n = w->sy / PANE_MINIMUM;
! 205: } else
! 206: height = w->sy / n;
! 207:
! 208: /* Fit the panes. */
! 209: i = yoff = 0;
! 210: TAILQ_FOREACH(wp, &w->panes, entry) {
! 211: if (i > n) {
! 212: wp->flags |= PANE_HIDDEN;
! 213: continue;
! 214: }
! 215: wp->flags &= ~PANE_HIDDEN;
! 216:
! 217: wp->xoff = 0;
! 218: wp->yoff = yoff;
! 219: if (i != n - 1)
! 220: window_pane_resize(wp, w->sx, height - 1);
! 221: else
! 222: window_pane_resize(wp, w->sx, height);
! 223:
! 224: i++;
! 225: yoff += height;
! 226: }
! 227:
! 228: /* Any space left? */
! 229: while (yoff++ < w->sy) {
! 230: wp = TAILQ_LAST(&w->panes, window_panes);
! 231: window_pane_resize(wp, wp->sx, wp->sy + 1);
! 232: }
! 233: }
! 234:
! 235: void
! 236: layout_main_v_refresh(struct window *w, int active_only)
! 237: {
! 238: struct window_pane *wp;
! 239: u_int i, n, mainwidth, height, yoff;
! 240:
! 241: if (active_only)
! 242: return;
! 243:
! 244: /* Get number of panes. */
! 245: n = window_count_panes(w);
! 246: if (n == 0)
! 247: return;
! 248:
! 249: /* Get the main pane width and add one for separator line. */
! 250: mainwidth = options_get_number(&w->options, "main-pane-width") + 1;
! 251:
! 252: /* Need >1 pane and minimum columns; if fewer, display active only. */
! 253: if (n == 1 || w->sx < mainwidth + PANE_MINIMUM) {
! 254: layout_active_only_refresh(w, active_only);
! 255: return;
! 256: }
! 257: n--;
! 258:
! 259: /* How many can we fit, not including first? */
! 260: if (w->sy / n < PANE_MINIMUM) {
! 261: height = PANE_MINIMUM;
! 262: n = w->sy / PANE_MINIMUM;
! 263: } else
! 264: height = w->sy / n;
! 265:
! 266: /* Fit the panes. */
! 267: i = yoff = 0;
! 268: TAILQ_FOREACH(wp, &w->panes, entry) {
! 269: if (wp == TAILQ_FIRST(&w->panes)) {
! 270: wp->xoff = 0;
! 271: wp->yoff = 0;
! 272: window_pane_resize(wp, mainwidth - 1, w->sy);
! 273: wp->flags &= ~PANE_HIDDEN;
! 274: continue;
! 275: }
! 276:
! 277: if (i > n) {
! 278: wp->flags |= PANE_HIDDEN;
! 279: continue;
! 280: }
! 281: wp->flags &= ~PANE_HIDDEN;
! 282:
! 283: wp->xoff = mainwidth;
! 284: wp->yoff = yoff;
! 285: if (i != n - 1)
! 286: window_pane_resize(wp, w->sx - mainwidth, height - 1);
! 287: else
! 288: window_pane_resize(wp, w->sx - mainwidth, height);
! 289:
! 290: i++;
! 291: yoff += height;
! 292: }
! 293:
! 294: /* Any space left? */
! 295: while (yoff++ < w->sy) {
! 296: wp = TAILQ_LAST(&w->panes, window_panes);
! 297: while (wp != NULL && wp == TAILQ_FIRST(&w->panes))
! 298: wp = TAILQ_PREV(wp, window_panes, entry);
! 299: if (wp == NULL)
! 300: break;
! 301: window_pane_resize(wp, wp->sx, wp->sy + 1);
! 302: }
! 303: }
! 304:
! 305: void
! 306: layout_main_h_refresh(struct window *w, int active_only)
! 307: {
! 308: struct window_pane *wp;
! 309: u_int i, n, mainheight, width, xoff;
! 310:
! 311: if (active_only)
! 312: return;
! 313:
! 314: /* Get number of panes. */
! 315: n = window_count_panes(w);
! 316: if (n == 0)
! 317: return;
! 318:
! 319: /* Get the main pane height and add one for separator line. */
! 320: mainheight = options_get_number(&w->options, "main-pane-height") + 1;
! 321:
! 322: /* Need >1 pane and minimum rows; if fewer, display active only. */
! 323: if (n == 1 || w->sy < mainheight + PANE_MINIMUM) {
! 324: layout_active_only_refresh(w, active_only);
! 325: return;
! 326: }
! 327: n--;
! 328:
! 329: /* How many can we fit, not including first? */
! 330: if (w->sx / n < PANE_MINIMUM) {
! 331: width = PANE_MINIMUM;
! 332: n = w->sx / PANE_MINIMUM;
! 333: } else
! 334: width = w->sx / n;
! 335:
! 336: /* Fit the panes. */
! 337: i = xoff = 0;
! 338: TAILQ_FOREACH(wp, &w->panes, entry) {
! 339: if (wp == TAILQ_FIRST(&w->panes)) {
! 340: wp->xoff = 0;
! 341: wp->yoff = 0;
! 342: window_pane_resize(wp, w->sx, mainheight - 1);
! 343: wp->flags &= ~PANE_HIDDEN;
! 344: continue;
! 345: }
! 346:
! 347: if (i > n) {
! 348: wp->flags |= PANE_HIDDEN;
! 349: continue;
! 350: }
! 351: wp->flags &= ~PANE_HIDDEN;
! 352:
! 353: wp->xoff = xoff;
! 354: wp->yoff = mainheight;
! 355: if (i != n - 1)
! 356: window_pane_resize(wp, width - 1, w->sy - mainheight);
! 357: else
! 358: window_pane_resize(wp, width - 1, w->sy - mainheight);
! 359:
! 360: i++;
! 361: xoff += width;
! 362: }
! 363:
! 364: /* Any space left? */
! 365: while (xoff++ < w->sx + 1) {
! 366: wp = TAILQ_LAST(&w->panes, window_panes);
! 367: while (wp != NULL && wp == TAILQ_FIRST(&w->panes))
! 368: wp = TAILQ_PREV(wp, window_panes, entry);
! 369: if (wp == NULL)
! 370: break;
! 371: window_pane_resize(wp, wp->sx + 1, wp->sy);
! 372: }
! 373: }