summaryrefslogtreecommitdiff
path: root/src/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout.c')
-rw-r--r--src/layout.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/src/layout.c b/src/layout.c
new file mode 100644
index 0000000..6100b5d
--- /dev/null
+++ b/src/layout.c
@@ -0,0 +1,367 @@
+/* Copyright (c) 2008, 2009
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Micah Cowan (micah@cowan.name)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "extern.h"
+#include "layout.h"
+
+extern struct display *display;
+extern int captionalways;
+
+struct layout *layouts;
+struct layout *laytab[MAXLAY];
+struct layout *layout_last, layout_last_marker;
+struct layout *layout_attach = &layout_last_marker;
+
+void
+FreeLayoutCv(cv)
+struct canvas *cv;
+{
+ struct canvas *cnext, *c = cv;
+ for (; cv; cv = cnext)
+ {
+ if (cv->c_slperp)
+ {
+ FreeLayoutCv(cv->c_slperp);
+ free(cv->c_slperp);
+ cv->c_slperp = 0;
+ }
+ cnext = cv->c_slnext;
+ cv->c_slnext = 0;
+ if (cv != c)
+ free(cv);
+ }
+}
+
+struct layout *
+CreateLayout(title, startat)
+char *title;
+int startat;
+{
+ struct layout *lay;
+ int i;
+
+ if (startat >= MAXLAY || startat < 0)
+ startat = 0;
+ for (i = startat; ;)
+ {
+ if (!laytab[i])
+ break;
+ if (++i == MAXLAY)
+ i = 0;
+ if (i == startat)
+ {
+ Msg(0, "No more layouts\n");
+ return 0;
+ }
+ }
+ lay = (struct layout *)calloc(1, sizeof(*lay));
+ lay->lay_title = SaveStr(title);
+ lay->lay_autosave = 1;
+ lay->lay_number = i;
+ laytab[i] = lay;
+ lay->lay_next = layouts;
+ layouts = lay;
+ return lay;
+}
+
+void
+SaveLayout(name, cv)
+char *name;
+struct canvas *cv;
+{
+ struct layout *lay;
+ struct canvas *fcv;
+ for (lay = layouts; lay; lay = lay->lay_next)
+ if (!strcmp(lay->lay_title, name))
+ break;
+ if (lay)
+ FreeLayoutCv(&lay->lay_canvas);
+ else
+ lay = CreateLayout(name, 0);
+ if (!lay)
+ return;
+ fcv = D_forecv;
+ DupLayoutCv(cv, &lay->lay_canvas, 1);
+ lay->lay_forecv = D_forecv;
+ D_forecv = fcv;
+ D_layout = lay;
+}
+
+void
+AutosaveLayout(lay)
+struct layout *lay;
+{
+ struct canvas *fcv;
+ if (!lay || !lay->lay_autosave)
+ return;
+ FreeLayoutCv(&lay->lay_canvas);
+ fcv = D_forecv;
+ DupLayoutCv(&D_canvas, &lay->lay_canvas, 1);
+ lay->lay_forecv = D_forecv;
+ D_forecv = fcv;
+}
+
+struct layout *
+FindLayout(name)
+char *name;
+{
+ struct layout *lay;
+ char *s;
+ int i;
+ for (i = 0, s = name; *s >= '0' && *s <= '9'; s++)
+ i = i * 10 + (*s - '0');
+ if (!*s && s != name && i >= 0 && i < MAXLAY)
+ return laytab[i];
+ for (lay = layouts; lay; lay = lay->lay_next)
+ if (!strcmp(lay->lay_title, name))
+ break;
+ return lay;
+}
+
+void
+LoadLayout(lay, cv)
+struct layout *lay;
+struct canvas *cv;
+{
+ AutosaveLayout(D_layout);
+ if (!lay)
+ {
+ while (D_canvas.c_slperp)
+ FreeCanvas(D_canvas.c_slperp);
+ MakeDefaultCanvas();
+ SetCanvasWindow(D_forecv, 0);
+ D_layout = 0;
+ return;
+ }
+ while (D_canvas.c_slperp)
+ FreeCanvas(D_canvas.c_slperp);
+ D_cvlist = 0;
+ D_forecv = lay->lay_forecv;
+ DupLayoutCv(&lay->lay_canvas, &D_canvas, 0);
+ D_canvas.c_ye = D_height - 1 - ((D_canvas.c_slperp && D_canvas.c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE);
+ ResizeCanvas(&D_canvas);
+ RecreateCanvasChain();
+ RethinkDisplayViewports();
+ PutWindowCv(&D_canvas);
+ ResizeLayersToCanvases();
+ D_layout = lay;
+}
+
+void
+NewLayout(title, startat)
+char *title;
+int startat;
+{
+ struct layout *lay;
+ struct canvas *fcv;
+
+ lay = CreateLayout(title, startat);
+ if (!lay)
+ return;
+ LoadLayout(0, &D_canvas);
+ fcv = D_forecv;
+ DupLayoutCv(&D_canvas, &lay->lay_canvas, 1);
+ lay->lay_forecv = D_forecv;
+ D_forecv = fcv;
+ D_layout = lay;
+ lay->lay_autosave = 1;
+}
+
+
+static char *
+AddLayoutsInfo(buf, len, where)
+char *buf;
+int len;
+int where;
+{
+ char *s, *ss, *t;
+ struct layout *p, **pp;
+ int l;
+
+ s = ss = buf;
+ for (pp = laytab; pp < laytab + MAXLAY; pp++)
+ {
+ if (pp - laytab == where && ss == buf)
+ ss = s;
+ if ((p = *pp) == 0)
+ continue;
+ t = p->lay_title;
+ l = strlen(t);
+ if (l > 20)
+ l = 20;
+ if (s - buf + l > len - 24)
+ break;
+ if (s > buf)
+ {
+ *s++ = ' ';
+ *s++ = ' ';
+ }
+ sprintf(s, "%d", p->lay_number);
+ if (p->lay_number == where)
+ ss = s;
+ s += strlen(s);
+ if (display && p == D_layout)
+ *s++ = '*';
+ *s++ = ' ';
+ strncpy(s, t, l);
+ s += l;
+ }
+ *s = 0;
+ return ss;
+}
+
+void
+ShowLayouts(where)
+int where;
+{
+ char buf[1024];
+ char *s, *ss;
+
+ if (!display)
+ return;
+ if (!layouts)
+ {
+ Msg(0, "No layouts defined\n");
+ return;
+ }
+ if (where == -1 && D_layout)
+ where = D_layout->lay_number;
+ ss = AddLayoutsInfo(buf, sizeof(buf), where);
+ s = buf + strlen(buf);
+ if (ss - buf > D_width / 2)
+ {
+ ss -= D_width / 2;
+ if (s - ss < D_width)
+ {
+ ss = s - D_width;
+ if (ss < buf)
+ ss = buf;
+ }
+ }
+ else
+ ss = buf;
+ Msg(0, "%s", ss);
+}
+
+void
+RemoveLayout(lay)
+struct layout *lay;
+{
+ struct layout **layp = &layouts;
+
+ for (; *layp; layp = &(*layp)->lay_next)
+ {
+ if (*layp == lay)
+ {
+ *layp = lay->lay_next;
+ break;
+ }
+ }
+ laytab[lay->lay_number] = (struct layout *)0;
+
+ if (display && D_layout == lay)
+ D_layout = (struct layout *)0;
+
+ FreeLayoutCv(&lay->lay_canvas);
+
+ if (lay->lay_title)
+ free(lay->lay_title);
+ free(lay);
+
+ if (layouts)
+ LoadLayout((display && D_layout) ? D_layout : *layp ? *layp : layouts,
+ display ? &D_canvas : (struct canvas *)0);
+ Activate(0);
+}
+
+void
+UpdateLayoutCanvas(cv, wi)
+struct canvas *cv;
+struct win *wi;
+{
+ for (; cv; cv = cv->c_slnext)
+ {
+ if (cv->c_layer && Layer2Window(cv->c_layer) == wi)
+ {
+ /* A simplistic version of SetCanvasWindow(cv, 0) */
+ struct layer *l = cv->c_layer;
+ cv->c_layer = 0;
+ if (l->l_cvlist == 0 && (wi == 0 || l != wi->w_savelayer))
+ KillLayerChain(l);
+ l = &cv->c_blank;
+ l->l_data = 0;
+ if (l->l_cvlist != cv)
+ {
+ cv->c_lnext = l->l_cvlist;
+ l->l_cvlist = cv;
+ }
+ cv->c_layer = l;
+ /* Do not end here. Multiple canvases can have the same window */
+ }
+
+ if (cv->c_slperp)
+ UpdateLayoutCanvas(cv->c_slperp, wi);
+ }
+}
+
+
+static void
+dump_canvas(cv, file)
+struct canvas *cv;
+FILE *file;
+{
+ struct canvas *c;
+ for (c = cv->c_slperp; c && c->c_slnext; c = c->c_slnext)
+ {
+ fprintf(file, "split%s\n", c->c_slorient == SLICE_HORI ? " -v" : "");
+ }
+
+ for (c = cv->c_slperp; c; c = c->c_slnext)
+ {
+ if (c->c_slperp)
+ dump_canvas(c, file);
+ else
+ fprintf(file, "focus\n");
+ }
+}
+
+int
+LayoutDumpCanvas(cv, filename)
+struct canvas *cv;
+char *filename;
+{
+ FILE *file = secfopen(filename, "a");
+ if (!file)
+ return 0;
+ dump_canvas(cv, file);
+ fclose(file);
+ return 1;
+}
+