[BACK]Return to layout.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

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: }