summaryrefslogtreecommitdiff
path: root/layer.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:23 +0200
committerAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:23 +0200
commitbdf45bc45637eefdbdee913465729f9d31d6c255 (patch)
tree9b6538c483ad6c2b38177068d5c5730397c9f292 /layer.c
parent14a4b00c9ef680b78469333291270e4c276f100d (diff)
downloadscreen-bdf45bc45637eefdbdee913465729f9d31d6c255.tar.gz
Imported Upstream version 3.9.5upstream/3.9.5
Diffstat (limited to 'layer.c')
-rw-r--r--layer.c938
1 files changed, 938 insertions, 0 deletions
diff --git a/layer.c b/layer.c
new file mode 100644
index 0000000..dfd40a8
--- /dev/null
+++ b/layer.c
@@ -0,0 +1,938 @@
+/* Copyright (c) 1993
+ * 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 2, 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, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ ****************************************************************
+ */
+
+#include "rcs.h"
+RCS_ID("$Id: search.c,v 1.2 1994/05/31 12:32:57 mlschroe Exp $ FAU")
+
+#include <sys/types.h>
+
+#include "config.h"
+#include "screen.h"
+#include "mark.h"
+#include "extern.h"
+#include "braille.h"
+
+extern struct display *display, *displays;
+
+extern struct mline mline_blank;
+extern struct mline mline_null;
+extern struct mchar mchar_null;
+extern struct mchar mchar_blank;
+
+extern struct layer *flayer; /* sigh */
+extern struct LayFuncs WinLf;
+extern struct LayFuncs BlankLf;
+
+
+static struct mline *mloff __P((struct mline *, int));
+
+/*
+ * Layer subsystem.
+ *
+ * ...here is all the clipping code... beware!
+ *
+ * XXX: add some speedup code!
+ *
+ */
+
+static struct mline *
+mloff(ml, off)
+struct mline *ml;
+int off;
+{
+ static struct mline mml;
+
+ if (ml == 0)
+ return 0;
+ mml.image = ml->image + off;
+ mml.attr = ml->attr + off;
+#ifdef FONT
+ mml.font = ml->font + off;
+#endif
+#ifdef COLOR
+ mml.color = ml->color + off;
+#endif
+ return &mml;
+}
+
+void
+LGotoPos(l, x, y)
+struct layer *l;
+int x, y;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int x2, y2;
+
+#ifdef HAVE_BRAILLE
+ if (bd.bd_refreshing)
+ return;
+#endif
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ if (cv != D_forecv)
+ continue;
+ x2 = x + cv->c_xoff;
+ y2 = y + cv->c_yoff;
+ debug2("---LGotoPos %d %d\n", x2, y2);
+ if (x2 < cv->c_xs)
+ x2 = cv->c_xs;
+ if (y2 < cv->c_ys)
+ y2 = cv->c_ys;
+ if (x2 > cv->c_xe)
+ x2 = cv->c_xe;
+ if (y2 > cv->c_ye)
+ y2 = cv->c_ye;
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ if (x2 < vp->v_xs || x2 > vp->v_xe)
+ continue;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ GotoPos(x2, y2);
+ break;
+ }
+ }
+}
+
+void
+LScrollH(l, n, y, xs, xe, ol)
+struct layer *l;
+int n, y, xs, xe;
+struct mline *ol;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int y2, xs2, xe2;
+
+ if (n == 0)
+ return;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ y2 = y + vp->v_yoff;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ xs2 = xs + vp->v_xoff;
+ xe2 = xe + vp->v_xoff;
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 > xe2)
+ continue;
+ display = cv->c_display;
+ ScrollH(y2, xs2, xe2, n, ol ? mloff(ol, -vp->v_xoff) : 0);
+ if (xe2 - xs2 == xe - xs)
+ continue;
+ if (n > 0)
+ {
+ xs2 = xe2 + 1 - n;
+ xe2 = xe + vp->v_xoff - n;
+ }
+ else
+ {
+ xe2 = xs2 - 1 - n;
+ xs2 = xs + vp->v_xoff - n;
+ }
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 <= xe2)
+ RefreshArea(xs2, y2, xe2, y2, 1);
+ }
+}
+
+void
+LScrollV(l, n, ys, ye)
+struct layer *l;
+int n;
+int ys, ye;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int ys2, ye2, xs2, xe2;
+ if (n == 0)
+ return;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ xs2 = vp->v_xoff;
+ xe2 = l->l_width - 1 + vp->v_xoff;
+ ys2 = ys + vp->v_yoff;
+ ye2 = ye + vp->v_yoff;
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (ys2 < vp->v_ys)
+ ys2 = vp->v_ys;
+ if (ye2 > vp->v_ye)
+ ye2 = vp->v_ye;
+ if (ys2 > ye2 || xs2 > xe2)
+ continue;
+ display = cv->c_display;
+#if 0
+ ScrollV(xs2, ys2, xe2, ye2, n);
+#else
+ ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n);
+#endif
+ debug2("LScrollV: %d %d", ys, ye);
+ debug2(" -> %d %d\n", ys2, ye2);
+ if (ye2 - ys2 == ye - ys)
+ continue;
+ if (n > 0)
+ {
+ ys2 = ye2 + 1 - n;
+ ye2 = ye + vp->v_yoff - n;
+ }
+ else
+ {
+ ye2 = ys2 - 1 - n;
+ ys2 = ys + vp->v_yoff - n;
+ }
+ debug2("LScrollV: - %d %d\n", ys2, ye2);
+ if (ys2 < vp->v_ys)
+ ys2 = vp->v_ys;
+ if (ye2 > vp->v_ye)
+ ye2 = vp->v_ye;
+ debug2("LScrollV: - %d %d\n", ys2, ye2);
+ if (ys2 <= ye2)
+ RefreshArea(xs2, ys2, xe2, ye2, 1);
+ }
+}
+
+void
+LInsChar(l, c, x, y, ol)
+struct layer *l;
+struct mchar *c;
+int x, y;
+struct mline *ol;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int xs2, xe2, y2, f;
+ struct mchar *c2, cc;
+
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ y2 = y + vp->v_yoff;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ xs2 = x + vp->v_xoff;
+ xe2 = l->l_width - 1 + vp->v_xoff;
+ c2 = c;
+ f = 0;
+ if (xs2 < vp->v_xs)
+ {
+ xs2 = vp->v_xs;
+ c2 = &mchar_blank;
+ if (ol)
+ {
+ int i;
+ i = xs2 - vp->v_xoff - 1;
+ if (i >= 0 && i < l->l_width)
+ {
+ copy_mline2mchar(&cc, ol, i);
+ c2 = &cc;
+ }
+ }
+ else
+ f = 1;
+ }
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 > xe2)
+ continue;
+ display = cv->c_display;
+ InsChar(c2, xs2, xe2, y2, mloff(ol, -vp->v_xoff));
+ if (f)
+ RefreshArea(xs2, y2, xs2, y2, 1);
+ }
+}
+
+void
+LPutChar(l, c, x, y)
+struct layer *l;
+struct mchar *c;
+int x, y;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int x2, y2;
+#ifdef HAVE_BRAILLE
+ if (bd.bd_refreshing)
+ {
+ BPutChar(l, c, x, y);
+ return;
+ }
+#endif
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ y2 = y + vp->v_yoff;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ x2 = x + vp->v_xoff;
+ if (x2 < vp->v_xs || x2 > vp->v_xe)
+ continue;
+ display = cv->c_display;
+ GotoPos(x2, y2);
+ SetRendition(c);
+ PUTCHARLP(c->image);
+ if (D_AM && !D_CLP && x2 == D_width - 1)
+ GotoPos(x2, y2);
+ }
+}
+
+void
+LPutStr(l, s, n, r, x, y)
+struct layer *l;
+char *s;
+int n;
+struct mchar *r;
+int x, y;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ char *s2;
+ int xs2, xe2, y2;
+
+ if (x + n > l->l_width)
+ n = l->l_width - x;
+#ifdef HAVE_BRAILLE
+ if (bd.bd_refreshing)
+ {
+ BPutStr(l, s, n, r, x, y);
+ return;
+ }
+#endif
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ y2 = y + vp->v_yoff;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ xs2 = x + vp->v_xoff;
+ xe2 = xs2 + n - 1;
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 > xe2)
+ continue;
+ display = cv->c_display;
+ GotoPos(xs2, y2);
+ SetRendition(r);
+ s2 = s + xs2 - x - vp->v_xoff;
+ while (xs2++ <= xe2)
+ PUTCHARLP(*s2++);
+ }
+}
+
+void
+LClearLine(l, y, xs, xe, ol)
+struct layer *l;
+int xs, xe;
+struct mline *ol;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int y2, xs2, xe2;
+
+ /* check for magic margin condition */
+ if (xs >= l->l_width)
+ xs = l->l_width - 1;
+ if (xe >= l->l_width)
+ xe = l->l_width - 1;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ xs2 = xs + vp->v_xoff;
+ xe2 = xe + vp->v_xoff;
+ y2 = y + vp->v_yoff;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 > xe2)
+ continue;
+ display = cv->c_display;
+ DisplayLine(ol ? mloff(ol, -vp->v_xoff) : &mline_null, &mline_blank, y2, xs2, xe2);
+ }
+}
+
+void
+LClear(l, xs, ys, xe, ye, uself)
+struct layer *l;
+int xs, ys, xe, ye;
+int uself;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int xs2, ys2, xe2, ye2;
+#ifdef HAVE_BRAILLE
+ if (bd.bd_refreshing)
+ return;
+#endif
+ /* check for magic margin condition */
+ if (xs >= l->l_width)
+ xs = l->l_width - 1;
+ if (xe >= l->l_width)
+ xe = l->l_width - 1;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ xs2 = xs + vp->v_xoff;
+ xe2 = xe + vp->v_xoff;
+ ys2 = ys + vp->v_yoff;
+ ye2 = ye + vp->v_yoff;
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 > vp->v_xe)
+ ys2++;
+ if (xe2 < vp->v_xs)
+ ye2--;
+ if (ys2 < vp->v_ys)
+ ys2 = vp->v_ys;
+ if (ye2 > vp->v_ye)
+ ye2 = vp->v_ye;
+ if (ys2 > ye2)
+ continue;
+#if 0
+ xcs = vp->v_xoff;
+ xce = l->l_width - 1 + vp->v_xoff;
+ if (xcs < vp->v_xs)
+ xcs = vp->v_xs;
+ if (xce > vp->v_xe)
+ xce = vp->v_xe;
+ if (xcs > xce)
+ continue;
+ if (ys2 != ys + vp->v_yoff)
+ xs2 = xcs;
+ if (ye2 != ye + vp->v_yoff)
+ xe2 = xce;
+ display = cv->c_display;
+ Clear(xs2, ys2, xcs, xce, xe2, ye2, uself);
+#else
+ if (xs == 0 || ys2 != ys + vp->v_yoff)
+ xs2 = vp->v_xs;
+ if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
+ xe2 = vp->v_xe;
+ display = cv->c_display;
+ Clear(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, uself);
+#endif
+ }
+}
+
+void
+LCDisplayLine(l, ml, y, xs, xe, isblank)
+struct layer *l;
+struct mline *ml;
+int y, xs, xe;
+int isblank;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+ int xs2, xe2, y2;
+#ifdef HAVE_BRAILLE
+ if (bd.bd_refreshing)
+ {
+ BCDisplayLine(l, ml, y, xs, xe, isblank);
+ return;
+ }
+#endif
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ xs2 = xs + vp->v_xoff;
+ xe2 = xe + vp->v_xoff;
+ y2 = y + vp->v_yoff;
+ if (y2 < vp->v_ys || y2 > vp->v_ye)
+ continue;
+ if (xs2 < vp->v_xs)
+ xs2 = vp->v_xs;
+ if (xe2 > vp->v_xe)
+ xe2 = vp->v_xe;
+ if (xs2 > xe2)
+ continue;
+ display = cv->c_display;
+ debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
+ debug1(" mloff = %d\n", -vp->v_xoff);
+ DisplayLine(isblank ? &mline_blank : &mline_null, mloff(ml, -vp->v_xoff), y2, xs2, xe2);
+ }
+}
+
+void
+LSetRendition(l, r)
+struct layer *l;
+struct mchar *r;
+{
+ struct canvas *cv;
+ struct viewport *vp;
+
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ display = cv->c_display;
+ SetRendition(r);
+ }
+}
+
+void
+LWrapChar(l, c, y, top, bot, ins)
+struct layer *l;
+struct mchar *c;
+int y, top, bot;
+int ins;
+{
+ struct canvas *cv, *cvlist, *cvlnext;
+ struct viewport *vp, *evp, **vpp;
+ int yy, y2, yy2, top2, bot2;
+
+ if (y != bot)
+ {
+ /* simple case: no scrolling */
+
+ /* cursor after wrapping */
+ yy = y == l->l_height - 1 ? y : y + 1;
+
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ /* find the viewport of the wrapped character */
+ for (vp = cv->c_vplist; vp; vp = vp->v_next)
+ {
+ y2 = y + vp->v_yoff;
+ yy2 = yy + vp->v_yoff;
+ if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
+ break;
+ }
+ if (vp == 0)
+ continue; /* nothing to do, character not visible */
+ /* find the viewport of the character at the end of the line*/
+ for (evp = cv->c_vplist; evp; evp = evp->v_next)
+ if (y2 >= evp->v_ys && y2 <= evp->v_ye && evp->v_xoff + l->l_width - 1 >= evp->v_xs && evp->v_xoff + l->l_width - 1 <= evp->v_xe)
+ break; /* gotcha! */
+ if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye))
+ {
+ /* no wrapping possible */
+ debug("LWrap: can't wrap!\n");
+ cvlist = l->l_cvlist;
+ cvlnext = cv->c_lnext;
+ l->l_cvlist = cv;
+ cv->c_lnext = 0;
+ if (ins)
+ LInsChar(l, c, 0, yy, 0);
+ else
+ LPutChar(l, c, 0, yy);
+ l->l_cvlist = cvlist;
+ cv->c_lnext = cvlnext;
+ }
+ else
+ WrapChar(c, vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
+ }
+ }
+ else
+ {
+ /* hard case: scroll up*/
+
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ /* search for wrap viewport */
+ for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next)
+ {
+ yy2 = bot + vp->v_yoff;
+ if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff + l->l_width - 1 <= vp->v_xe)
+ break;
+ }
+
+ if (vp)
+ {
+ /* great, can use Wrap on the vp */
+ /* temporarily remove vp from cvlist */
+ *vpp = vp->v_next;
+ }
+ if (cv->c_vplist)
+ {
+ /* scroll all viewports != vp */
+ cvlist = l->l_cvlist;
+ cvlnext = cv->c_lnext;
+ l->l_cvlist = cv;
+ cv->c_lnext = 0;
+ LScrollV(l, 1, top, bot);
+ if (!vp)
+ {
+ if (ins)
+ LInsChar(l, c, 0, bot, 0);
+ else
+ LPutChar(l, c, 0, bot);
+ }
+ l->l_cvlist = cvlist;
+ cv->c_lnext = cvlnext;
+ }
+ if (vp)
+ {
+ /* add vp back to cvlist */
+ *vpp = vp;
+ top2 = top + vp->v_yoff;
+ bot2 = bot + vp->v_yoff;
+ if (top2 < vp->v_ys)
+ top2 = vp->v_ys;
+ WrapChar(c, vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
+ }
+ }
+ }
+}
+
+
+void
+LCursorVisibility(l, vis)
+struct layer *l;
+int vis;
+{
+ struct canvas *cv;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ if (cv != D_forecv)
+ continue;
+ CursorVisibility(vis);
+ }
+}
+
+void
+LSetFlow(l, flow)
+struct layer *l;
+int flow;
+{
+ struct canvas *cv;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ if (cv != D_forecv)
+ continue;
+ SetFlow(flow);
+ }
+}
+
+void
+LKeypadMode(l, on)
+struct layer *l;
+int on;
+{
+ struct canvas *cv;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ if (cv != D_forecv)
+ continue;
+ KeypadMode(on);
+ }
+}
+
+void
+LCursorkeysMode(l, on)
+struct layer *l;
+int on;
+{
+ struct canvas *cv;
+ for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ display = cv->c_display;
+ if (cv != D_forecv)
+ continue;
+ CursorkeysMode(on);
+ }
+}
+
+
+/*******************************************************************/
+
+void
+ClearLayer(l, uself)
+struct layer *l;
+int uself;
+{
+ LClear(l, 0, 0, l->l_width - 1, l->l_height - 1, uself);
+}
+
+void
+RedisplayLayer(l, isblank)
+struct layer *l;
+int isblank;
+{
+ struct layer *oldflayer;
+ int y;
+
+ debug1("RedisplayLayer isblank=%d\n", isblank);
+ oldflayer = flayer;
+ flayer = l;
+ if (!isblank)
+ LClear(l, 0, 0, l->l_width - 1, l->l_height - 1, 0);
+ /* signal full refresh */
+ RedisplayLine(-1, -1, -1, 1);
+ for (y = 0; y < l->l_height; y++)
+ RedisplayLine(y, 0, l->l_width - 1, 1);
+ flayer = oldflayer;
+}
+
+
+void
+KillLayerChain(lay)
+struct layer *lay;
+{
+ struct canvas *cv, *ncv;
+ struct layer *l, *oldflayer;
+
+ oldflayer = flayer;
+ debug1("KillLayerChain %#x\n", lay);
+ for (l = lay; l; l = l->l_next)
+ {
+ if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
+ break;
+ debug1("- killing %#x\n", l);
+ if (oldflayer == l)
+ oldflayer = 0;
+ for (cv = l->l_cvlist; cv; cv = ncv)
+ {
+ ncv = cv->c_lnext;
+ cv->c_layer = 0;
+ cv->c_lnext = 0;
+ }
+ }
+ flayer = lay;
+ while (flayer != l)
+ ExitOverlayPage();
+ flayer = oldflayer;
+}
+
+
+/*******************************************************************/
+/*******************************************************************/
+
+/*
+ * Layer creation / removal
+ */
+
+int
+InitOverlayPage(datasize, lf, block)
+int datasize;
+struct LayFuncs *lf;
+int block;
+{
+ char *data;
+ struct layer *newlay;
+ struct canvas *cv, *cvp, **cvpp;
+ struct win *p;
+
+ ASSERT(flayer);
+
+ cv = 0;
+ if (display && D_forecv->c_layer == flayer)
+ cv = D_forecv; /* work only on this cv! */
+
+ if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0)
+ {
+ Msg(0, "No memory for layer struct");
+ return -1;
+ }
+ debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
+ data = 0;
+ if (datasize)
+ {
+ if ((data = malloc(datasize)) == 0)
+ {
+ free((char *)newlay);
+ Msg(0, "No memory for layer data");
+ return -1;
+ }
+ bzero(data, datasize);
+ }
+
+ p = Layer2Window(flayer);
+
+ if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0)))
+ {
+ if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0)
+ KillLayerChain(p->w_savelayer);
+ p->w_savelayer = newlay;
+ }
+
+ if (cv && flayer->l_next == 0 && !block)
+ {
+ struct display *olddisplay = display;
+ display = cv->c_display;
+ RemoveStatus();
+ display = olddisplay;
+
+ /* new branch -> just get canvas vps */
+ for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
+ if (cvp == cv)
+ break;
+ ASSERT(cvp);
+ *cvpp = cv->c_lnext;
+ newlay->l_cvlist = cv;
+ cv->c_lnext = 0;
+ cv->c_layer = newlay;
+ }
+ else
+ {
+ LAY_DISPLAYS(flayer, RemoveStatus());
+ if (block)
+ debug("layer is blocking\n");
+ if (block && flayer->l_layfn == &WinLf)
+ {
+ debug("...and is first, so window gets blocked\n");
+ ASSERT(p->w_blocked == 0);
+ p->w_blocked++;
+ newlay->l_blocking = 1;
+ }
+ /* change all canvases */
+ newlay->l_cvlist = flayer->l_cvlist;
+ for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
+ cvp->c_layer = newlay;
+ flayer->l_cvlist = 0;
+ }
+ newlay->l_width = flayer->l_width;
+ newlay->l_height = flayer->l_height;
+ newlay->l_layfn = lf;
+ newlay->l_data = data;
+ newlay->l_next = flayer;
+ newlay->l_bottom = flayer->l_bottom;
+ flayer = newlay;
+ Restore();
+ return 0;
+}
+
+void
+ExitOverlayPage()
+{
+ struct layer *oldlay;
+ struct win *p;
+ int doredisplay = 0;
+ struct canvas *cv, *ocv;
+
+ ASSERT(flayer);
+ debug1("Exiting layer %#x\n", (unsigned int)flayer);
+ oldlay = flayer;
+ if (oldlay->l_data)
+ free(oldlay->l_data);
+
+ p = Layer2Window(flayer);
+
+ flayer = oldlay->l_next;
+ if (flayer->l_layfn == &WinLf)
+ {
+ if (oldlay->l_blocking)
+ {
+ ASSERT(p->w_blocked > 0);
+ p->w_blocked--;
+ debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked);
+ }
+ /* don't warp dead layers: check cvlist */
+ if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist)
+ {
+ debug("warping to top of blocking chain!\n");
+ /* warp ourself into savelayer */
+ flayer = p->w_savelayer;
+ doredisplay = 1;
+ }
+ }
+ if (p && p->w_savelayer == oldlay)
+ p->w_savelayer = flayer;
+#ifdef COPY_PASTE
+ if (p && oldlay == p->w_paster.pa_pastelayer)
+ p->w_paster.pa_pastelayer = 0;
+#endif
+
+ /* add all canvases back into next layer's canvas list */
+ for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext)
+ {
+ cv->c_layer = flayer;
+ ocv = cv;
+ }
+ if (ocv)
+ {
+ cv = flayer->l_cvlist;
+ ocv->c_lnext = 0;
+ flayer->l_cvlist = oldlay->l_cvlist;
+ /* redisplay only the warped cvs */
+ if (doredisplay)
+ RedisplayLayer(flayer, 0);
+ ocv->c_lnext = cv;
+ }
+ oldlay->l_cvlist = 0;
+ free((char *)oldlay);
+ Restore();
+ SetCursor();
+}
+
+void
+/*VARARGS2*/
+#if defined(USEVARARGS) && defined(__STDC__)
+LMsg(int err, char *fmt, VA_DOTS)
+#else
+LMsg(err, fmt, VA_DOTS)
+int err;
+char *fmt;
+VA_DECL
+#endif
+{
+ VA_LIST(ap)
+ char buf[MAXPATHLEN*2];
+ char *p = buf;
+ struct canvas *cv;
+
+ VA_START(ap, fmt);
+ fmt = DoNLS(fmt);
+ (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
+ VA_END(ap);
+ if (err)
+ {
+ p += strlen(p);
+ *p++ = ':';
+ *p++ = ' ';
+ strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
+ buf[sizeof(buf) - 1] = 0;
+ }
+ debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
+ for (display = displays; display; display = display->d_next)
+ {
+ for (cv = D_cvlist; cv; cv = cv->c_next)
+ if (cv->c_layer == flayer)
+ break;
+ if (cv == 0)
+ continue;
+ MakeStatus(buf);
+ }
+}
+