1
0
Fork 0
screen/layout.c
Daniel Baumann e88291c4cd
Adding upstream version 4.9.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 15:19:57 +02:00

350 lines
8 KiB
C

/* 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;
}