summaryrefslogtreecommitdiffstats
path: root/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'layout.c')
-rw-r--r--layout.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/layout.c b/layout.c
new file mode 100644
index 0000000..c69d4b5
--- /dev/null
+++ b/layout.c
@@ -0,0 +1,350 @@
+/* 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
+ * https://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(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(char *title, int startat)
+{
+ struct layout *lay, **pl;
+ 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 = 0;
+
+ pl = &layouts;
+ while (*pl)
+ pl = &(*pl)->lay_next;
+ *pl = lay;
+ return lay;
+}
+
+void SaveLayout(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(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(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(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;
+ if (!D_forecv)
+ MakeDefaultCanvas();
+ DupLayoutCv(&lay->lay_canvas, &D_canvas, 0);
+ D_canvas.c_ys = (D_has_hstatus == HSTATUS_FIRSTLINE);
+ 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(char *title, int startat)
+{
+ struct layout *lay;
+ struct canvas *fcv;
+
+ lay = CreateLayout(title, startat);
+ if (!lay)
+ return;
+
+ if (display) {
+ 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;
+ }
+ else
+ layout_attach = lay;
+
+ lay->lay_autosave = 1;
+}
+
+
+static char *AddLayoutsInfo(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(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(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(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(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(struct canvas *cv, char *filename)
+{
+ FILE *file = secfopen(filename, "a");
+ if (!file)
+ return 0;
+ dump_canvas(cv, file);
+ fclose(file);
+ return 1;
+}
+
+void RenameLayout(struct layout *layout, const char *name)
+{
+ free(layout->lay_title);
+ layout->lay_title = SaveStr(name);
+}
+
+int RenumberLayout(struct layout *layout, int number)
+{
+ int old;
+ struct layout *lay;
+ old = layout->lay_number;
+ if (number < 0 || number >= MAXLAY)
+ return 0;
+ lay = laytab[number];
+ laytab[number] = layout;
+ layout->lay_number = number;
+ laytab[old] = lay;
+ if (lay)
+ lay->lay_number = old;
+ return 1;
+}