Update of /cvsroot/tmux/tmux
In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv22478

Modified Files:
        cmd-list-windows.c cmd-select-layout.c layout-string.c 
        layout.c tmux.1 tmux.h 
Added Files:
        layout-custom.c 
Log Message:
Sync OpenBSD patchset 732:

Custom layouts. list-windows command displays the layout as a string (such as
"bb62,159x48,0,0{79x48,0,0,79x48,80,0}") and it can be applied to another
window (with the same number of panes or fewer) using select-layout.


Index: tmux.1
===================================================================
RCS file: /cvsroot/tmux/tmux/tmux.1,v
retrieving revision 1.262
retrieving revision 1.263
diff -u -d -r1.262 -r1.263
--- tmux.1      2 Jul 2010 02:49:19 -0000       1.262
+++ tmux.1      2 Jul 2010 02:54:52 -0000       1.263
@@ -14,7 +14,7 @@
 .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: June 27 2010 $
+.Dd $Mdocdate: June 29 2010 $
 .Dt TMUX 1
 .Os
 .Sh NAME
@@ -877,6 +877,24 @@
 columns.
 .El
 .Pp
+In addition,
+.Ic select-layout
+may be used to apply a previously used layout - the
+.Ic list-windows
+command displays the layout of each window in a form suitable for use with
+.Ic select-layout .
+For example:
+.Bd -literal -offset indent
+$ tmux list-windows
+0: ksh [159x48]
+    layout: bb62,159x48,0,0{79x48,0,0,79x48,80,0}
+$ tmux select-layout bb62,159x48,0,0{79x48,0,0,79x48,80,0}
+.Ed
+.Nm
+automatically adjusts the size of the layout for the current window size.
+Note that a layout cannot be applied to a window with more panes than that
+from which the layout was originally defined.
+.Pp
 Commands related to windows and panes are as follows:
 .Bl -tag -width Ds
 .It Xo Ic break-pane
@@ -1224,7 +1242,7 @@
 Choose a specific layout for a window.
 If
 .Ar layout-name
-is not given, the last layout used (if any) is reapplied.
+is not given, the last preset layout used (if any) is reapplied.
 .It Xo Ic select-pane
 .Op Fl DLRU
 .Op Fl t Ar target-pane

--- NEW FILE: layout-custom.c ---
/* $Id: layout-custom.c,v 1.1 2010/07/02 02:54:52 tcunha Exp $ */

/*
 * Copyright (c) 2010 Nicholas Marriott <[email protected]>
 *
 * 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 <ctype.h>
#include <string.h>

#include "tmux.h"

u_short                 layout_checksum(const char *);
int                     layout_append(struct layout_cell *, char *, size_t);
struct layout_cell     *layout_construct(struct layout_cell *, const char **);
void                    layout_assign(struct window_pane **, struct layout_cell 
*);

/* Calculate layout checksum. */
u_short
layout_checksum(const char *layout)
{
        u_short csum;

        csum = 0;
        for (; *layout != '\0'; layout++) {
                csum = (csum >> 1) + ((csum & 1) << 15);
                csum += *layout;
        }
        return (csum);
}

/* Dump layout as a string. */
char *
layout_dump(struct window *w)
{
        char    layout[BUFSIZ], *out;

        *layout = '\0';
        if (layout_append(w->layout_root, layout, sizeof layout) != 0)
                return (NULL);

        xasprintf(&out, "%4x,%s", layout_checksum(layout), layout);
        return (out);
}

/* Append information for a single cell. */
int
layout_append(struct layout_cell *lc, char *buf, size_t len)
{
        struct layout_cell     *lcchild;
        char                    tmp[64];
        size_t                  tmplen;
        const char             *brackets = "][";

        if (len == 0)
                return (-1);

        tmplen = xsnprintf(tmp, sizeof tmp,
            "%ux%u,%u,%u", lc->sx, lc->sy, lc->xoff, lc->yoff);
        if (tmplen > (sizeof tmp) - 1)
                return (-1);
        if (strlcat(buf, tmp, len) >= len)
                return (-1);

        switch (lc->type) {
        case LAYOUT_LEFTRIGHT:
                brackets = "}{";
                /* FALLTHROUGH */
        case LAYOUT_TOPBOTTOM:
                if (strlcat(buf, &brackets[1], len) >= len)
                        return (-1);
                TAILQ_FOREACH(lcchild, &lc->cells, entry) {
                        if (layout_append(lcchild, buf, len) != 0)
                                return (-1);
                        if (strlcat(buf, ",", len) >= len)
                                return (-1);
                }
                buf[strlen(buf) - 1] = brackets[0];
                break;
        case LAYOUT_WINDOWPANE:
                break;
        }

        return (0);
}

/* Parse a layout string and arrange window as layout. */
int
layout_parse(struct window *w, const char *layout)
{
        struct layout_cell      *lc, *lcchild;
        struct window_pane      *wp;
        u_int                    npanes, ncells, sx, sy;
        u_short                  csum;

        /* Check validity. */
        if (sscanf(layout, "%hx,", &csum) != 1)
                return (-1);
        layout += 5;
        if (csum != layout_checksum(layout))
                return (-1);

        /* Build the layout. */
        lc = layout_construct(NULL, &layout);
        if (lc == NULL)
                return (-1);
        if (*layout != '\0')
                goto fail;

        /* Check this window will fit into the layout. */
        for (;;) {
                npanes = window_count_panes(w);
                ncells = layout_count_cells(lc);
                if (npanes > ncells)
                        goto fail;
                if (npanes == ncells)
                        break;

                /* Fewer panes than cells - close the bottom right. */
                lcchild = layout_find_bottomright(lc);
                layout_destroy_cell(lcchild, &lc);
        }

        /* Save the old window size and resize to the layout size. */
        sx = w->sx; sy = w->sy;
        window_resize(w, lc->sx, lc->sy);

        /* Destroy the old layout and swap to the new. */
        layout_free_cell(w->layout_root);
        w->layout_root = lc;

        /* Assign the panes into the cells. */
        wp = TAILQ_FIRST(&w->panes);
        layout_assign(&wp, lc);

        /* Update pane offsets and sizes. */
        layout_fix_offsets(lc);
        layout_fix_panes(w, lc->sx, lc->sy);

        /* Then resize the layout back to the original window size. */
        layout_resize(w, sx, sy);
        window_resize(w, sx, sy);

        layout_print_cell(lc, __func__, 0);

        return (0);

fail:
        layout_free_cell(lc);
        return (-1);
}

/* Assign panes into cells. */
void
layout_assign(struct window_pane **wp, struct layout_cell *lc)
{
        struct layout_cell      *lcchild;

        switch (lc->type) {
        case LAYOUT_WINDOWPANE:
                layout_make_leaf(lc, *wp);
                *wp = TAILQ_NEXT(*wp, entry);
                return;
        case LAYOUT_LEFTRIGHT:
        case LAYOUT_TOPBOTTOM:
                TAILQ_FOREACH(lcchild, &lc->cells, entry)
                        layout_assign(wp, lcchild);
                return;
        }
}

/* Construct a cell from all or part of a layout tree. */
struct layout_cell *
layout_construct(struct layout_cell *lcparent, const char **layout)
{
        struct layout_cell     *lc, *lcchild;
        u_int                   sx, sy, xoff, yoff;

        if (!isdigit((u_char) **layout))
                return (NULL);
        if (sscanf(*layout, "%ux%u,%u,%u", &sx, &sy, &xoff, &yoff) != 4)
                return (NULL);

        while (isdigit((u_char) **layout))
                (*layout)++;
        if (**layout != 'x')
                return (NULL);
        (*layout)++;
        while (isdigit((u_char) **layout))
                (*layout)++;
        if (**layout != ',')
                return (NULL);
        (*layout)++;
        while (isdigit((u_char) **layout))
                (*layout)++;
        if (**layout != ',')
                return (NULL);
        (*layout)++;
        while (isdigit((u_char) **layout))
                (*layout)++;

        lc = layout_create_cell(lcparent);
        lc->sx = sx;
        lc->sy = sy;
        lc->xoff = xoff;
        lc->yoff = yoff;

        switch (**layout) {
        case ',':
        case '}':
        case ']':
        case '\0':
                return (lc);
        case '{':
                lc->type = LAYOUT_LEFTRIGHT;
                break;
        case '[':
                lc->type = LAYOUT_TOPBOTTOM;
                break;
        default:
                goto fail;
        }

        do {
                (*layout)++;
                lcchild = layout_construct(lc, layout);
                if (lcchild == NULL)
                        goto fail;
                TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
        } while (**layout == ',');

        switch (lc->type) {
        case LAYOUT_LEFTRIGHT:
                if (**layout != '}')
                        goto fail;
                break;
        case LAYOUT_TOPBOTTOM:
                if (**layout != ']')
                        goto fail;
                break;
        default:
                goto fail;
        }
        (*layout)++;

        return (lc);

fail:
        layout_free_cell(lc);
        return (NULL);
}

Index: layout.c
===================================================================
RCS file: /cvsroot/tmux/tmux/layout.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- layout.c    8 Jan 2010 16:31:35 -0000       1.18
+++ layout.c    2 Jul 2010 02:54:52 -0000       1.19
@@ -218,6 +218,27 @@
        }
 }
 
+/* Count the number of available cells in a layout. */
+u_int
+layout_count_cells(struct layout_cell *lc)
+{
+       struct layout_cell      *lcchild;
+       u_int                    n;
+
+       switch (lc->type) {
+       case LAYOUT_WINDOWPANE:
+               return (1);
+       case LAYOUT_LEFTRIGHT:
+       case LAYOUT_TOPBOTTOM:
+               n = 0;
+               TAILQ_FOREACH(lcchild, &lc->cells, entry)
+                       n += layout_count_cells(lcchild);
+               return (n);
+       default:
+               fatalx("bad layout type");
+       }
+}
+
 /* Calculate how much size is available to be removed from a cell. */
 u_int
 layout_resize_check(struct layout_cell *lc, enum layout_type type)
@@ -302,6 +323,56 @@
        }
 }
 
+/* Destroy a cell and redistribute the space. */
+void
+layout_destroy_cell(struct layout_cell *lc, struct layout_cell **lcroot)
+{
+       struct layout_cell     *lcother, *lcparent;
+
+       /*
+        * If no parent, this is the last pane so window close is imminent and
+        * there is no need to resize anything.
+        */
+       lcparent = lc->parent;
+       if (lcparent == NULL) {
+               layout_free_cell(lc);
+               *lcroot = NULL;
+               return;
+       }
+
+       /* Merge the space into the previous or next cell. */
+       if (lc == TAILQ_FIRST(&lcparent->cells))
+               lcother = TAILQ_NEXT(lc, entry);
+       else
+               lcother = TAILQ_PREV(lc, layout_cells, entry);
+       if (lcparent->type == LAYOUT_LEFTRIGHT)
+               layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
+       else
+               layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
+
+       /* Remove this from the parent's list. */
+       TAILQ_REMOVE(&lcparent->cells, lc, entry);
+       layout_free_cell(lc);
+
+       /*
+        * If the parent now has one cell, remove the parent from the tree and
+        * replace it by that cell.
+        */
+       lc = TAILQ_FIRST(&lcparent->cells);
+       if (TAILQ_NEXT(lc, entry) == NULL) {
+               TAILQ_REMOVE(&lcparent->cells, lc, entry);
+
+               lc->parent = lcparent->parent;
+               if (lc->parent == NULL) {
+                       lc->xoff = 0; lc->yoff = 0;
+                       *lcroot = lc;
+               } else
+                       TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
+
+               layout_free_cell(lcparent);
+       }
+}
+
 void
 layout_init(struct window *w)
 {
@@ -597,59 +668,16 @@
        return (lcnew);
 }
 
-/* Destroy the layout associated with a pane and redistribute the space. */
+/* Destroy the cell associated with a pane. */
 void
 layout_close_pane(struct window_pane *wp)
 {
-       struct layout_cell     *lc, *lcother, *lcparent;
-
-       lc = wp->layout_cell;
-       lcparent = lc->parent;
-
-       /*
-        * If no parent, this is the last pane so window close is imminent and
-        * there is no need to resize anything.
-        */
-       if (lcparent == NULL) {
-               layout_free_cell(lc);
-               wp->window->layout_root = NULL;
-               return;
-       }
-
-       /* Merge the space into the previous or next cell. */
-       if (lc == TAILQ_FIRST(&lcparent->cells))
-               lcother = TAILQ_NEXT(lc, entry);
-       else
-               lcother = TAILQ_PREV(lc, layout_cells, entry);
-       if (lcparent->type == LAYOUT_LEFTRIGHT)
-               layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
-       else
-               layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
-
-       /* Remove this from the parent's list. */
-       TAILQ_REMOVE(&lcparent->cells, lc, entry);
-       layout_free_cell(lc);
-
-       /*
-        * If the parent now has one cell, remove the parent from the tree and
-        * replace it by that cell.
-        */
-       lc = TAILQ_FIRST(&lcparent->cells);
-       if (TAILQ_NEXT(lc, entry) == NULL) {
-               TAILQ_REMOVE(&lcparent->cells, lc, entry);
-
-               lc->parent = lcparent->parent;
-               if (lc->parent == NULL) {
-                       lc->xoff = 0; lc->yoff = 0;
-                       wp->window->layout_root = lc;
-               } else
-                       TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
-
-               layout_free_cell(lcparent);
-       }
+       /* Remove the cell. */
+       layout_destroy_cell(wp->layout_cell, &wp->window->layout_root);
 
        /* Fix pane offsets and sizes. */
-       layout_fix_offsets(wp->window->layout_root);
-       layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
+       if (wp->window->layout_root != NULL) {
+               layout_fix_offsets(wp->window->layout_root);
+               layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
+       }
 }
-

Index: cmd-list-windows.c
===================================================================
RCS file: /cvsroot/tmux/tmux/cmd-list-windows.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- cmd-list-windows.c  14 Nov 2009 17:56:39 -0000      1.42
+++ cmd-list-windows.c  2 Jul 2010 02:54:52 -0000       1.43
@@ -45,6 +45,7 @@
        struct cmd_target_data  *data = self->data;
        struct session          *s;
        struct winlink          *wl;
+       char                    *layout;
 
        if ((s = cmd_find_session(ctx, data->target)) == NULL)
                return (-1);
@@ -52,6 +53,9 @@
        RB_FOREACH(wl, winlinks, &s->windows) {
                ctx->print(ctx, "%d: %s [%ux%u]",
                    wl->idx, wl->window->name, wl->window->sx, wl->window->sy);
+               layout = layout_dump(wl->window);
+               ctx->print(ctx, "    layout: %s", layout);
+               xfree(layout);
        }
 
        return (0);

Index: layout-string.c
===================================================================
RCS file: /cvsroot/tmux/tmux/layout-string.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- layout-string.c     8 Jan 2010 16:28:04 -0000       1.3
+++ layout-string.c     2 Jul 2010 02:54:52 -0000       1.4
@@ -36,7 +36,6 @@
 struct layout_cell *layout_find_topleft(struct layout_cell *);
 struct layout_cell *layout_find_topright(struct layout_cell *);
 struct layout_cell *layout_find_bottomleft(struct layout_cell *);
-struct layout_cell *layout_find_bottomright(struct layout_cell *);
 
 /* Find the cell; returns NULL if string not understood. */
 struct layout_cell *

Index: cmd-select-layout.c
===================================================================
RCS file: /cvsroot/tmux/tmux/cmd-select-layout.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- cmd-select-layout.c 14 May 2010 14:16:37 -0000      1.11
+++ cmd-select-layout.c 2 Jul 2010 02:54:52 -0000       1.12
@@ -79,13 +79,16 @@
                layout = wl->window->lastlayout;
                if (layout == -1)
                        return (0);
-       } else if ((layout = layout_set_lookup(data->arg)) == -1) {
-               ctx->error(ctx, "unknown layout or ambiguous: %s", data->arg);
-               return (-1);
+       } else if ((layout = layout_set_lookup(data->arg)) != -1) {
+               layout = layout_set_select(wl->window, layout);
+               ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
+       } else {
+               if (layout_parse(wl->window, data->arg) == -1) {
+                       ctx->error(ctx, "can't set layout: %s", data->arg);
+                       return (-1);
+               }
+               ctx->info(ctx, "arranging in: %s", data->arg);
        }
 
-       layout = layout_set_select(wl->window, layout);
-       ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
-
        return (0);
 }

Index: tmux.h
===================================================================
RCS file: /cvsroot/tmux/tmux/tmux.h,v
retrieving revision 1.567
retrieving revision 1.568
diff -u -d -r1.567 -r1.568
--- tmux.h      2 Jul 2010 02:52:13 -0000       1.567
+++ tmux.h      2 Jul 2010 02:54:52 -0000       1.568
@@ -1849,9 +1849,11 @@
 struct window_pane *window_pane_find_right(struct window_pane *);
 
 /* layout.c */
+u_int           layout_count_cells(struct layout_cell *);
 struct layout_cell *layout_create_cell(struct layout_cell *);
 void            layout_free_cell(struct layout_cell *);
 void            layout_print_cell(struct layout_cell *, const char *, u_int);
+void            layout_destroy_cell(struct layout_cell *, struct layout_cell 
**);
 void            layout_set_size(
                     struct layout_cell *, u_int, u_int, u_int, u_int);
 void            layout_make_leaf(
@@ -1872,6 +1874,10 @@
                     struct window_pane *, enum layout_type, int);
 void            layout_close_pane(struct window_pane *);
 
+/* layout-custom.c */
+char           *layout_dump(struct window *);
+int             layout_parse(struct window *, const char *);
+
 /* layout-set.c */
 const char     *layout_set_name(u_int);
 int             layout_set_lookup(const char *);
@@ -1882,6 +1888,7 @@
 
 /* layout-string.c */
 struct layout_cell *layout_find_string(struct window *, const char *);
+struct layout_cell *layout_find_bottomright(struct layout_cell *);
 
 /* window-clock.c */
 extern const struct window_mode window_clock_mode;


------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
tmux-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-cvs

Reply via email to