[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.2

1.2     ! nicm        1: /* $OpenBSD: layout.c,v 1.1 2009/06/01 22:58:49 nicm Exp $ */
1.1       nicm        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;
1.2     ! nicm      128:        u_int                    xoff;
1.1       nicm      129:
1.2     ! nicm      130:        xoff = w->sx;
1.1       nicm      131:        TAILQ_FOREACH(wp, &w->panes, entry) {
1.2     ! nicm      132:                /* Put the active pane on screen and the rest to the right. */
        !           133:                if (wp == w->active)
        !           134:                        wp->xoff = 0;
        !           135:                else {
        !           136:                        wp->xoff = xoff;
        !           137:                        xoff += w->sx;
        !           138:                }
        !           139:                wp->yoff = 0;
        !           140:                window_pane_resize(wp, w->sx, w->sy);
1.1       nicm      141:        }
                    142: }
                    143:
                    144: void
                    145: layout_even_h_refresh(struct window *w, int active_only)
                    146: {
                    147:        struct window_pane      *wp;
                    148:        u_int                    i, n, width, xoff;
                    149:
                    150:        if (active_only)
                    151:                return;
                    152:
1.2     ! nicm      153:        /* If the screen is too small, show active only. */
        !           154:        if (w->sx < PANE_MINIMUM || w->sy < PANE_MINIMUM) {
        !           155:                layout_active_only_refresh(w, active_only);
        !           156:                return;
        !           157:        }
        !           158:
1.1       nicm      159:        /* Get number of panes. */
                    160:        n = window_count_panes(w);
                    161:        if (n == 0)
                    162:                return;
                    163:
                    164:        /* How many can we fit? */
                    165:        if (w->sx / n < PANE_MINIMUM) {
                    166:                width = PANE_MINIMUM;
1.2     ! nicm      167:                n = UINT_MAX;
1.1       nicm      168:        } else
                    169:                width = w->sx / n;
                    170:
                    171:        /* Fit the panes. */
                    172:        i = xoff = 0;
                    173:        TAILQ_FOREACH(wp, &w->panes, entry) {
                    174:                wp->xoff = xoff;
                    175:                wp->yoff = 0;
                    176:                if (i != n - 1)
                    177:                        window_pane_resize(wp, width - 1, w->sy);
                    178:                else
                    179:                        window_pane_resize(wp, width, w->sy);
                    180:
                    181:                i++;
                    182:                xoff += width;
                    183:        }
                    184:
                    185:        /* Any space left? */
                    186:        while (xoff++ < w->sx) {
                    187:                wp = TAILQ_LAST(&w->panes, window_panes);
                    188:                window_pane_resize(wp, wp->sx + 1, wp->sy);
                    189:        }
                    190: }
                    191:
                    192: void
                    193: layout_even_v_refresh(struct window *w, int active_only)
                    194: {
                    195:        struct window_pane      *wp;
                    196:        u_int                    i, n, height, yoff;
                    197:
                    198:        if (active_only)
                    199:                return;
                    200:
1.2     ! nicm      201:        /* If the screen is too small, show active only. */
        !           202:        if (w->sx < PANE_MINIMUM || w->sy < PANE_MINIMUM) {
        !           203:                layout_active_only_refresh(w, active_only);
        !           204:                return;
        !           205:        }
        !           206:
1.1       nicm      207:        /* Get number of panes. */
                    208:        n = window_count_panes(w);
                    209:        if (n == 0)
                    210:                return;
                    211:
                    212:        /* How many can we fit? */
                    213:        if (w->sy / n < PANE_MINIMUM) {
                    214:                height = PANE_MINIMUM;
1.2     ! nicm      215:                n = UINT_MAX;
1.1       nicm      216:        } else
                    217:                height = w->sy / n;
                    218:
                    219:        /* Fit the panes. */
                    220:        i = yoff = 0;
                    221:        TAILQ_FOREACH(wp, &w->panes, entry) {
                    222:                wp->xoff = 0;
                    223:                wp->yoff = yoff;
                    224:                if (i != n - 1)
                    225:                        window_pane_resize(wp, w->sx, height - 1);
                    226:                else
                    227:                        window_pane_resize(wp, w->sx, height);
                    228:
                    229:                i++;
                    230:                yoff += height;
                    231:        }
                    232:
                    233:        /* Any space left? */
                    234:        while (yoff++ < w->sy) {
                    235:                wp = TAILQ_LAST(&w->panes, window_panes);
                    236:                window_pane_resize(wp, wp->sx, wp->sy + 1);
                    237:        }
                    238: }
                    239:
                    240: void
                    241: layout_main_v_refresh(struct window *w, int active_only)
                    242: {
                    243:        struct window_pane      *wp;
                    244:        u_int                    i, n, mainwidth, height, yoff;
                    245:
                    246:        if (active_only)
                    247:                return;
                    248:
                    249:        /* Get number of panes. */
                    250:        n = window_count_panes(w);
                    251:        if (n == 0)
                    252:                return;
                    253:
                    254:        /* Get the main pane width and add one for separator line. */
                    255:        mainwidth = options_get_number(&w->options, "main-pane-width") + 1;
                    256:
                    257:        /* Need >1 pane and minimum columns; if fewer, display active only. */
1.2     ! nicm      258:        if (n == 1 ||
        !           259:            w->sx < mainwidth + PANE_MINIMUM || w->sy < PANE_MINIMUM) {
1.1       nicm      260:                layout_active_only_refresh(w, active_only);
                    261:                return;
                    262:        }
                    263:        n--;
                    264:
                    265:        /* How many can we fit, not including first? */
                    266:        if (w->sy / n < PANE_MINIMUM) {
                    267:                height = PANE_MINIMUM;
                    268:                n = w->sy / PANE_MINIMUM;
                    269:        } else
                    270:                height = w->sy / n;
                    271:
                    272:        /* Fit the panes. */
                    273:        i = yoff = 0;
                    274:        TAILQ_FOREACH(wp, &w->panes, entry) {
                    275:                if (wp == TAILQ_FIRST(&w->panes)) {
                    276:                        wp->xoff = 0;
                    277:                        wp->yoff = 0;
                    278:                        window_pane_resize(wp, mainwidth - 1, w->sy);
                    279:                        continue;
                    280:                }
                    281:
                    282:                wp->xoff = mainwidth;
                    283:                wp->yoff = yoff;
                    284:                if (i != n - 1)
                    285:                        window_pane_resize(wp, w->sx - mainwidth, height - 1);
                    286:                else
                    287:                        window_pane_resize(wp, w->sx - mainwidth, height);
                    288:
                    289:                i++;
                    290:                yoff += height;
                    291:        }
                    292:
                    293:        /* Any space left? */
                    294:        while (yoff++ < w->sy) {
                    295:                wp = TAILQ_LAST(&w->panes, window_panes);
                    296:                while (wp != NULL && wp == TAILQ_FIRST(&w->panes))
                    297:                        wp = TAILQ_PREV(wp, window_panes, entry);
                    298:                if (wp == NULL)
                    299:                        break;
                    300:                window_pane_resize(wp, wp->sx, wp->sy + 1);
                    301:        }
                    302: }
                    303:
                    304: void
                    305: layout_main_h_refresh(struct window *w, int active_only)
                    306: {
                    307:        struct window_pane      *wp;
                    308:        u_int                    i, n, mainheight, width, xoff;
                    309:
                    310:        if (active_only)
                    311:                return;
                    312:
                    313:        /* Get number of panes. */
                    314:        n = window_count_panes(w);
                    315:        if (n == 0)
                    316:                return;
                    317:
                    318:        /* Get the main pane height and add one for separator line. */
                    319:        mainheight = options_get_number(&w->options, "main-pane-height") + 1;
                    320:
                    321:        /* Need >1 pane and minimum rows; if fewer, display active only. */
1.2     ! nicm      322:        if (n == 1 ||
        !           323:            w->sy < mainheight + PANE_MINIMUM || w->sx < PANE_MINIMUM) {
1.1       nicm      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:                        continue;
                    344:                }
                    345:
                    346:                wp->xoff = xoff;
                    347:                wp->yoff = mainheight;
                    348:                if (i != n - 1)
                    349:                        window_pane_resize(wp, width - 1, w->sy - mainheight);
                    350:                else
                    351:                        window_pane_resize(wp, width - 1, w->sy - mainheight);
                    352:
                    353:                i++;
                    354:                xoff += width;
                    355:        }
                    356:
                    357:        /* Any space left? */
                    358:        while (xoff++ < w->sx + 1) {
                    359:                wp = TAILQ_LAST(&w->panes, window_panes);
                    360:                while (wp != NULL && wp == TAILQ_FIRST(&w->panes))
                    361:                        wp = TAILQ_PREV(wp, window_panes, entry);
                    362:                if (wp == NULL)
                    363:                        break;
                    364:                window_pane_resize(wp, wp->sx + 1, wp->sy);
                    365:        }
                    366: }