First working version of new event dispatching framwork.
[screen-lua.git] / src / layer.c
blob487e45e9db2f1f30f4ea7624a2eaf0e2f512f51c
1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
14 * any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
31 #include "config.h"
32 #include "screen.h"
33 #include "mark.h"
34 #include "extern.h"
35 #include "braille.h"
37 extern struct display *display, *displays;
39 extern struct mline mline_blank, mline_null;
40 extern struct mchar mchar_blank, mchar_null;
42 extern struct layer *flayer; /* sigh */
43 extern struct LayFuncs WinLf;
44 extern struct LayFuncs BlankLf;
47 static struct mline *mloff __P((struct mline *, int));
50 * Layer subsystem.
52 * ...here is all the clipping code... beware!
54 * XXX: add some speedup code!
58 static struct mline *
59 mloff(ml, off)
60 struct mline *ml;
61 int off;
63 static struct mline mml;
65 if (ml == 0)
66 return 0;
67 mml.image = ml->image + off;
68 mml.attr = ml->attr + off;
69 #ifdef FONT
70 mml.font = ml->font + off;
71 #endif
72 #ifdef COLOR
73 mml.color = ml->color + off;
74 # ifdef COLORS256
75 mml.colorx = ml->colorx + off;
76 # endif
77 #endif
78 return &mml;
81 #ifdef UTF8
82 # define RECODE_MCHAR(mc) ((l->l_encoding == UTF8) != (D_encoding == UTF8) ? recode_mchar(mc, l->l_encoding, D_encoding) : (mc))
83 # define RECODE_MLINE(ml) ((l->l_encoding == UTF8) != (D_encoding == UTF8) ? recode_mline(ml, l->l_width, l->l_encoding, D_encoding) : (ml))
84 #else
85 # define RECODE_MCHAR(mc) (mc)
86 # define RECODE_MLINE(ml) (ml)
87 #endif
90 void
91 LGotoPos(l, x, y)
92 struct layer *l;
93 int x, y;
95 struct canvas *cv;
96 struct viewport *vp;
97 int x2, y2;
99 #ifdef HAVE_BRAILLE
100 if (bd.bd_refreshing)
101 return;
102 #endif
103 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
105 display = cv->c_display;
106 if (D_blocked)
107 continue;
108 if (cv != D_forecv)
109 continue;
110 x2 = x + cv->c_xoff;
111 y2 = y + cv->c_yoff;
112 debug2("---LGotoPos %d %d\n", x2, y2);
113 if (x2 < cv->c_xs)
114 x2 = cv->c_xs;
115 if (y2 < cv->c_ys)
116 y2 = cv->c_ys;
117 if (x2 > cv->c_xe)
118 x2 = cv->c_xe;
119 if (y2 > cv->c_ye)
120 y2 = cv->c_ye;
121 for (vp = cv->c_vplist; vp; vp = vp->v_next)
123 if (x2 < vp->v_xs || x2 > vp->v_xe)
124 continue;
125 if (y2 < vp->v_ys || y2 > vp->v_ye)
126 continue;
127 GotoPos(x2, y2);
128 break;
133 void
134 LScrollH(l, n, y, xs, xe, bce, ol)
135 struct layer *l;
136 int n, y, xs, xe;
137 int bce;
138 struct mline *ol;
140 struct canvas *cv;
141 struct viewport *vp;
142 int y2, xs2, xe2;
144 if (n == 0)
145 return;
146 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
147 for (vp = cv->c_vplist; vp; vp = vp->v_next)
149 y2 = y + vp->v_yoff;
150 if (y2 < vp->v_ys || y2 > vp->v_ye)
151 continue;
152 xs2 = xs + vp->v_xoff;
153 xe2 = xe + vp->v_xoff;
154 if (xs2 < vp->v_xs)
155 xs2 = vp->v_xs;
156 if (xe2 > vp->v_xe)
157 xe2 = vp->v_xe;
158 if (xs2 > xe2)
159 continue;
160 display = cv->c_display;
161 if (D_blocked)
162 continue;
163 ScrollH(y2, xs2, xe2, n, bce, ol ? mloff(ol, -vp->v_xoff) : 0);
164 if (xe2 - xs2 == xe - xs)
165 continue;
166 if (n > 0)
168 xs2 = xe2 + 1 - n;
169 xe2 = xe + vp->v_xoff - n;
171 else
173 xe2 = xs2 - 1 - n;
174 xs2 = xs + vp->v_xoff - n;
176 if (xs2 < vp->v_xs)
177 xs2 = vp->v_xs;
178 if (xe2 > vp->v_xe)
179 xe2 = vp->v_xe;
180 if (xs2 <= xe2)
181 RefreshArea(xs2, y2, xe2, y2, 1);
185 void
186 LScrollV(l, n, ys, ye, bce)
187 struct layer *l;
188 int n;
189 int ys, ye;
190 int bce;
192 struct canvas *cv;
193 struct viewport *vp;
194 int ys2, ye2, xs2, xe2;
195 if (n == 0)
196 return;
197 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
198 for (vp = cv->c_vplist; vp; vp = vp->v_next)
200 xs2 = vp->v_xoff;
201 xe2 = l->l_width - 1 + vp->v_xoff;
202 ys2 = ys + vp->v_yoff;
203 ye2 = ye + vp->v_yoff;
204 if (xs2 < vp->v_xs)
205 xs2 = vp->v_xs;
206 if (xe2 > vp->v_xe)
207 xe2 = vp->v_xe;
208 if (ys2 < vp->v_ys)
209 ys2 = vp->v_ys;
210 if (ye2 > vp->v_ye)
211 ye2 = vp->v_ye;
212 if (ys2 > ye2 || xs2 > xe2)
213 continue;
214 display = cv->c_display;
215 if (D_blocked)
216 continue;
217 #if 0
218 ScrollV(xs2, ys2, xe2, ye2, n, bce);
219 #else
220 ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n, bce);
221 #endif
222 debug2("LScrollV: %d %d", ys, ye);
223 debug2(" -> %d %d\n", ys2, ye2);
224 if (ye2 - ys2 == ye - ys)
225 continue;
226 if (n > 0)
228 ys2 = ye2 + 1 - n;
229 ye2 = ye + vp->v_yoff - n;
231 else
233 ye2 = ys2 - 1 - n;
234 ys2 = ys + vp->v_yoff - n;
236 debug2("LScrollV: - %d %d\n", ys2, ye2);
237 if (ys2 < vp->v_ys)
238 ys2 = vp->v_ys;
239 if (ye2 > vp->v_ye)
240 ye2 = vp->v_ye;
241 debug2("LScrollV: - %d %d\n", ys2, ye2);
242 if (ys2 <= ye2)
243 RefreshArea(xs2, ys2, xe2, ye2, 1);
247 void
248 LInsChar(l, c, x, y, ol)
249 struct layer *l;
250 struct mchar *c;
251 int x, y;
252 struct mline *ol;
254 struct canvas *cv;
255 struct viewport *vp;
256 int xs2, xe2, y2, f;
257 struct mchar *c2, cc;
258 struct mline *rol;
260 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
261 for (vp = cv->c_vplist; vp; vp = vp->v_next)
263 y2 = y + vp->v_yoff;
264 if (y2 < vp->v_ys || y2 > vp->v_ye)
265 continue;
266 xs2 = x + vp->v_xoff;
267 xe2 = l->l_width - 1 + vp->v_xoff;
268 c2 = c;
269 f = 0;
270 if (xs2 < vp->v_xs)
272 xs2 = vp->v_xs;
273 c2 = &mchar_blank;
274 if (ol)
276 int i;
277 i = xs2 - vp->v_xoff - 1;
278 if (i >= 0 && i < l->l_width)
280 copy_mline2mchar(&cc, ol, i);
281 c2 = &cc;
284 else
285 f = 1;
287 if (xe2 > vp->v_xe)
288 xe2 = vp->v_xe;
289 if (xs2 > xe2)
290 continue;
291 display = cv->c_display;
292 if (D_blocked)
293 continue;
294 rol = RECODE_MLINE(ol);
295 InsChar(RECODE_MCHAR(c2), xs2, xe2, y2, mloff(rol, -vp->v_xoff));
296 if (f)
297 RefreshArea(xs2, y2, xs2, y2, 1);
301 void
302 LPutChar(l, c, x, y)
303 struct layer *l;
304 struct mchar *c;
305 int x, y;
307 struct canvas *cv;
308 struct viewport *vp;
309 int x2, y2;
310 #ifdef HAVE_BRAILLE
311 if (bd.bd_refreshing)
313 BPutChar(l, c, x, y);
314 return;
316 #endif
317 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
319 display = cv->c_display;
320 if (D_blocked)
321 continue;
322 for (vp = cv->c_vplist; vp; vp = vp->v_next)
324 y2 = y + vp->v_yoff;
325 if (y2 < vp->v_ys || y2 > vp->v_ye)
326 continue;
327 x2 = x + vp->v_xoff;
328 if (x2 < vp->v_xs || x2 > vp->v_xe)
329 continue;
330 PutChar(RECODE_MCHAR(c), x2, y2);
331 break;
336 void
337 LPutStr(l, s, n, r, x, y)
338 struct layer *l;
339 char *s;
340 int n;
341 struct mchar *r;
342 int x, y;
344 struct canvas *cv;
345 struct viewport *vp;
346 char *s2;
347 int xs2, xe2, y2;
349 if (x + n > l->l_width)
350 n = l->l_width - x;
351 #ifdef HAVE_BRAILLE
352 if (bd.bd_refreshing)
354 BPutStr(l, s, n, r, x, y);
355 return;
357 #endif
358 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
359 for (vp = cv->c_vplist; vp; vp = vp->v_next)
361 y2 = y + vp->v_yoff;
362 if (y2 < vp->v_ys || y2 > vp->v_ye)
363 continue;
364 xs2 = x + vp->v_xoff;
365 xe2 = xs2 + n - 1;
366 if (xs2 < vp->v_xs)
367 xs2 = vp->v_xs;
368 if (xe2 > vp->v_xe)
369 xe2 = vp->v_xe;
370 if (xs2 > xe2)
371 continue;
372 display = cv->c_display;
373 if (D_blocked)
374 continue;
375 GotoPos(xs2, y2);
376 SetRendition(r);
377 s2 = s + xs2 - x - vp->v_xoff;
378 #ifdef UTF8
379 if (D_encoding == UTF8 && l->l_encoding != UTF8 && (r->font || l->l_encoding))
381 struct mchar mc;
382 mc = *r;
383 while (xs2 <= xe2)
385 mc.image = *s2++;
386 PutChar(RECODE_MCHAR(&mc), xs2++, y2);
388 continue;
390 #endif
391 while (xs2++ <= xe2)
392 PUTCHARLP(*s2++);
396 void
397 LPutWinMsg(l, s, n, r, x, y)
398 struct layer *l;
399 char *s;
400 int n;
401 struct mchar *r;
402 int x, y;
404 struct canvas *cv;
405 struct viewport *vp;
406 int xs2, xe2, y2, len, len2;
407 struct mchar or;
409 if (x + n > l->l_width)
410 n = l->l_width - x;
411 #ifdef HAVE_BRAILLE
412 if (bd.bd_refreshing)
414 BPutStr(l, s, n, r, x, y);
415 return;
417 #endif
418 len = strlen(s);
419 if (len > n)
420 len = n;
421 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
422 for (vp = cv->c_vplist; vp; vp = vp->v_next)
424 y2 = y + vp->v_yoff;
425 if (y2 < vp->v_ys || y2 > vp->v_ye)
426 continue;
427 xs2 = x + vp->v_xoff;
428 xe2 = xs2 + n - 1;
429 if (xs2 < vp->v_xs)
430 xs2 = vp->v_xs;
431 if (xe2 > vp->v_xe)
432 xe2 = vp->v_xe;
433 if (xs2 > xe2)
434 continue;
435 display = cv->c_display;
436 if (D_blocked)
437 continue;
438 GotoPos(xs2, y2);
439 SetRendition(r);
440 len2 = xe2 - (x + vp->v_xoff) + 1;
441 if (len2 > len)
442 len2 = len;
443 PutWinMsg(s, xs2 - x - vp->v_xoff, len2);
444 xs2 = x + vp->v_xoff + len2;
445 if (xs2 < vp->v_xs)
446 xs2 = vp->v_xs;
447 or = D_rend;
448 GotoPos(xs2, y2);
449 SetRendition(&or);
450 while (xs2++ <= xe2)
451 PUTCHARLP(' ');
455 void
456 LClearLine(l, y, xs, xe, bce, ol)
457 struct layer *l;
458 int xs, xe, bce;
459 struct mline *ol;
461 struct canvas *cv;
462 struct viewport *vp;
463 int y2, xs2, xe2;
465 /* check for magic margin condition */
466 if (xs >= l->l_width)
467 xs = l->l_width - 1;
468 if (xe >= l->l_width)
469 xe = l->l_width - 1;
470 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
471 for (vp = cv->c_vplist; vp; vp = vp->v_next)
473 xs2 = xs + vp->v_xoff;
474 xe2 = xe + vp->v_xoff;
475 y2 = y + vp->v_yoff;
476 if (y2 < vp->v_ys || y2 > vp->v_ye)
477 continue;
478 if (xs2 < vp->v_xs)
479 xs2 = vp->v_xs;
480 if (xe2 > vp->v_xe)
481 xe2 = vp->v_xe;
482 if (xs2 > xe2)
483 continue;
484 display = cv->c_display;
485 if (D_blocked)
486 continue;
487 ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
491 void
492 LClearArea(l, xs, ys, xe, ye, bce, uself)
493 struct layer *l;
494 int xs, ys, xe, ye;
495 int bce;
496 int uself;
498 struct canvas *cv;
499 struct viewport *vp;
500 int xs2, ys2, xe2, ye2;
501 #ifdef HAVE_BRAILLE
502 if (bd.bd_refreshing)
503 return;
504 #endif
505 /* Check for zero-height window */
506 if (ys < 0 || ye < ys)
507 return;
509 /* check for magic margin condition */
510 if (xs >= l->l_width)
511 xs = l->l_width - 1;
512 if (xe >= l->l_width)
513 xe = l->l_width - 1;
514 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
516 display = cv->c_display;
517 if (D_blocked)
518 continue;
519 for (vp = cv->c_vplist; vp; vp = vp->v_next)
521 xs2 = xs + vp->v_xoff;
522 xe2 = xe + vp->v_xoff;
523 ys2 = ys + vp->v_yoff;
524 ye2 = ye + vp->v_yoff;
525 if (xs2 < vp->v_xs)
526 xs2 = vp->v_xs;
527 if (xe2 > vp->v_xe)
528 xe2 = vp->v_xe;
529 if (xs2 > vp->v_xe)
530 ys2++;
531 if (xe2 < vp->v_xs)
532 ye2--;
533 if (ys2 < vp->v_ys)
534 ys2 = vp->v_ys;
535 if (ye2 > vp->v_ye)
536 ye2 = vp->v_ye;
537 if (ys2 > ye2)
538 continue;
539 #if 0
540 xcs = vp->v_xoff;
541 xce = l->l_width - 1 + vp->v_xoff;
542 if (xcs < vp->v_xs)
543 xcs = vp->v_xs;
544 if (xce > vp->v_xe)
545 xce = vp->v_xe;
546 if (xcs > xce)
547 continue;
548 if (ys2 != ys + vp->v_yoff)
549 xs2 = xcs;
550 if (ye2 != ye + vp->v_yoff)
551 xe2 = xce;
552 display = cv->c_display;
553 ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself);
554 #else
555 if (xs == 0 || ys2 != ys + vp->v_yoff)
556 xs2 = vp->v_xs;
557 if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
558 xe2 = vp->v_xe;
559 display = cv->c_display;
560 ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself);
561 #endif
566 void
567 LCDisplayLine(l, ml, y, xs, xe, isblank)
568 struct layer *l;
569 struct mline *ml;
570 int y, xs, xe;
571 int isblank;
573 struct canvas *cv;
574 struct viewport *vp;
575 int xs2, xe2, y2;
576 #ifdef HAVE_BRAILLE
577 if (bd.bd_refreshing)
579 BCDisplayLine(l, ml, y, xs, xe, isblank);
580 return;
582 #endif
583 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
585 display = cv->c_display;
586 if (D_blocked)
587 continue;
588 for (vp = cv->c_vplist; vp; vp = vp->v_next)
590 xs2 = xs + vp->v_xoff;
591 xe2 = xe + vp->v_xoff;
592 y2 = y + vp->v_yoff;
593 if (y2 < vp->v_ys || y2 > vp->v_ye)
594 continue;
595 if (xs2 < vp->v_xs)
596 xs2 = vp->v_xs;
597 if (xe2 > vp->v_xe)
598 xe2 = vp->v_xe;
599 if (xs2 > xe2)
600 continue;
601 display = cv->c_display;
602 debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
603 debug1(" mloff = %d\n", -vp->v_xoff);
604 DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
609 void
610 LCDisplayLineWrap(l, ml, y, from, to, isblank)
611 struct layer *l;
612 struct mline *ml;
613 int y, from, to;
614 int isblank;
616 struct mchar nc;
617 copy_mline2mchar(&nc, ml, 0);
618 #ifdef DW_CHARS
619 if (dw_left(ml, 0, l->l_encoding))
621 nc.mbcs = ml->image[1];
622 from++;
624 #endif
625 LWrapChar(l, &nc, y - 1, -1, -1, 0);
626 from++;
627 if (from <= to)
628 LCDisplayLine(l, ml, y, from, to, isblank);
631 void
632 LSetRendition(l, r)
633 struct layer *l;
634 struct mchar *r;
636 struct canvas *cv;
638 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
640 display = cv->c_display;
641 if (D_blocked)
642 continue;
643 SetRendition(r);
647 void
648 LWrapChar(l, c, y, top, bot, ins)
649 struct layer *l;
650 struct mchar *c;
651 int y, top, bot;
652 int ins;
654 struct canvas *cv, *cvlist, *cvlnext;
655 struct viewport *vp, *evp, **vpp;
656 int yy, y2, yy2, top2, bot2;
657 int bce;
659 #ifdef COLOR
660 bce = rend_getbg(c);
661 #else
662 bce = 0;
663 #endif
664 if (y != bot)
666 /* simple case: no scrolling */
668 /* cursor after wrapping */
669 yy = y == l->l_height - 1 ? y : y + 1;
671 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
673 y2 = 0; /* gcc -Wall */
674 display = cv->c_display;
675 if (D_blocked)
676 continue;
677 /* find the viewport of the wrapped character */
678 for (vp = cv->c_vplist; vp; vp = vp->v_next)
680 y2 = y + vp->v_yoff;
681 yy2 = yy + vp->v_yoff;
682 if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
683 break;
685 if (vp == 0)
686 continue; /* nothing to do, character not visible */
687 /* find the viewport of the character at the end of the line*/
688 for (evp = cv->c_vplist; evp; evp = evp->v_next)
689 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)
690 break; /* gotcha! */
691 if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye))
693 /* no wrapping possible */
694 debug("LWrap: can't wrap!\n");
695 cvlist = l->l_cvlist;
696 cvlnext = cv->c_lnext;
697 l->l_cvlist = cv;
698 cv->c_lnext = 0;
699 if (ins)
700 LInsChar(l, c, 0, yy, 0);
701 else
702 LPutChar(l, c, 0, yy);
703 l->l_cvlist = cvlist;
704 cv->c_lnext = cvlnext;
706 else
708 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
712 else
714 /* hard case: scroll up*/
716 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
718 display = cv->c_display;
719 if (D_blocked)
720 continue;
721 /* search for wrap viewport */
722 for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next)
724 yy2 = bot + vp->v_yoff;
725 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)
726 break;
729 if (vp)
731 /* great, can use Wrap on the vp */
732 /* temporarily remove vp from cvlist */
733 *vpp = vp->v_next;
735 if (cv->c_vplist)
737 /* scroll all viewports != vp */
738 cvlist = l->l_cvlist;
739 cvlnext = cv->c_lnext;
740 l->l_cvlist = cv;
741 cv->c_lnext = 0;
742 LScrollV(l, 1, top, bot, bce);
743 if (!vp)
745 if (ins)
746 LInsChar(l, c, 0, bot, 0);
747 else
748 LPutChar(l, c, 0, bot);
750 l->l_cvlist = cvlist;
751 cv->c_lnext = cvlnext;
753 if (vp)
755 /* add vp back to cvlist */
756 *vpp = vp;
757 top2 = top + vp->v_yoff;
758 bot2 = bot + vp->v_yoff;
759 if (top2 < vp->v_ys)
760 top2 = vp->v_ys;
761 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
768 void
769 LCursorVisibility(l, vis)
770 struct layer *l;
771 int vis;
773 struct canvas *cv;
774 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
776 display = cv->c_display;
777 if (D_blocked)
778 continue;
779 if (cv != D_forecv)
780 continue;
781 CursorVisibility(vis);
785 void
786 LSetFlow(l, flow)
787 struct layer *l;
788 int flow;
790 struct canvas *cv;
791 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
793 display = cv->c_display;
794 if (cv != D_forecv)
795 continue;
796 SetFlow(flow);
800 void
801 LKeypadMode(l, on)
802 struct layer *l;
803 int on;
805 struct canvas *cv;
806 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
808 display = cv->c_display;
809 if (D_blocked)
810 continue;
811 if (cv != D_forecv)
812 continue;
813 KeypadMode(on);
817 void
818 LCursorkeysMode(l, on)
819 struct layer *l;
820 int on;
822 struct canvas *cv;
823 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
825 display = cv->c_display;
826 if (D_blocked)
827 continue;
828 if (cv != D_forecv)
829 continue;
830 CursorkeysMode(on);
834 void
835 LMouseMode(l, on)
836 struct layer *l;
837 int on;
839 struct canvas *cv;
840 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
842 display = cv->c_display;
843 if (D_blocked)
844 continue;
845 if (cv != D_forecv)
846 continue;
847 MouseMode(on);
851 void
852 LClearAll(l, uself)
853 struct layer *l;
854 int uself;
856 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
859 void
860 LRefreshAll(l, isblank)
861 struct layer *l;
862 int isblank;
864 struct layer *oldflayer;
865 int y;
867 debug1("LRefreshAll isblank=%d\n", isblank);
868 oldflayer = flayer;
869 flayer = l;
870 if (!isblank)
871 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0);
872 /* signal full refresh */
873 LayRedisplayLine(-1, -1, -1, 1);
874 for (y = 0; y < l->l_height; y++)
875 LayRedisplayLine(y, 0, l->l_width - 1, 1);
876 flayer = oldflayer;
879 void
880 /*VARARGS2*/
881 #if defined(USEVARARGS) && defined(__STDC__)
882 LMsg(int err, char *fmt, VA_DOTS)
883 #else
884 LMsg(err, fmt, VA_DOTS)
885 int err;
886 char *fmt;
887 VA_DECL
888 #endif
890 VA_LIST(ap)
891 char buf[MAXPATHLEN*2];
892 char *p = buf;
893 struct canvas *cv;
895 VA_START(ap, fmt);
896 fmt = DoNLS(fmt);
897 (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
898 VA_END(ap);
899 if (err)
901 p += strlen(p);
902 *p++ = ':';
903 *p++ = ' ';
904 strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
905 buf[sizeof(buf) - 1] = 0;
907 debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
908 for (display = displays; display; display = display->d_next)
910 for (cv = D_cvlist; cv; cv = cv->c_next)
911 if (cv->c_layer == flayer)
912 break;
913 if (cv == 0)
914 continue;
915 MakeStatus(buf);
920 /*******************************************************************/
921 /*******************************************************************/
924 * Layer creation / removal
927 void
928 KillLayerChain(lay)
929 struct layer *lay;
931 struct canvas *cv, *ncv;
932 struct layer *l, *oldflayer;
934 oldflayer = flayer;
935 debug1("KillLayerChain %#x\n", lay);
936 for (l = lay; l; l = l->l_next)
938 if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
939 break;
940 debug1("- killing %#x\n", l);
941 if (oldflayer == l)
942 oldflayer = 0;
943 for (cv = l->l_cvlist; cv; cv = ncv)
945 ncv = cv->c_lnext;
946 cv->c_layer = 0;
947 cv->c_lnext = 0;
950 flayer = lay;
951 while (flayer != l)
952 ExitOverlayPage();
953 flayer = oldflayer;
959 InitOverlayPage(datasize, lf, block)
960 int datasize;
961 struct LayFuncs *lf;
962 int block;
964 char *data;
965 struct layer *newlay;
966 struct canvas *cv, *cvp, **cvpp;
967 struct win *p;
969 ASSERT(flayer);
971 cv = 0;
972 if (display && D_forecv->c_layer == flayer)
973 cv = D_forecv; /* work only on this cv! */
975 if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0)
977 Msg(0, "No memory for layer struct");
978 return -1;
980 debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
981 data = 0;
982 if (datasize)
984 if ((data = calloc(1, datasize)) == 0)
986 free((char *)newlay);
987 Msg(0, "No memory for layer data");
988 return -1;
992 p = Layer2Window(flayer);
994 if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0)))
996 if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0)
997 KillLayerChain(p->w_savelayer);
998 p->w_savelayer = newlay;
1001 if (cv && flayer->l_next == 0 && !block)
1003 struct display *olddisplay = display;
1004 display = cv->c_display;
1005 RemoveStatus();
1006 display = olddisplay;
1008 /* new branch -> just get canvas vps */
1009 for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
1010 if (cvp == cv)
1011 break;
1012 ASSERT(cvp);
1013 *cvpp = cv->c_lnext;
1014 newlay->l_cvlist = cv;
1015 cv->c_lnext = 0;
1016 cv->c_layer = newlay;
1018 else
1020 LAY_DISPLAYS(flayer, RemoveStatus());
1021 if (block)
1022 debug("layer is blocking\n");
1023 if (block && flayer->l_layfn == &WinLf)
1025 debug("...and is first, so window gets blocked\n");
1026 ASSERT(p->w_blocked == 0);
1027 p->w_blocked++;
1028 newlay->l_blocking = 1;
1030 /* change all canvases */
1031 newlay->l_cvlist = flayer->l_cvlist;
1032 for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
1033 cvp->c_layer = newlay;
1034 flayer->l_cvlist = 0;
1036 newlay->l_width = flayer->l_width;
1037 newlay->l_height = flayer->l_height;
1038 newlay->l_encoding = 0;
1039 newlay->l_layfn = lf;
1040 newlay->l_data = data;
1041 newlay->l_next = flayer;
1042 newlay->l_bottom = flayer->l_bottom;
1043 flayer = newlay;
1044 LayRestore();
1045 return 0;
1048 extern struct layout *layouts;
1050 void
1051 ExitOverlayPage()
1053 struct layer *oldlay;
1054 struct win *p;
1055 int doredisplay = 0;
1056 struct canvas *cv, *ocv;
1057 struct layout *lay;
1059 ASSERT(flayer);
1060 debug1("Exiting layer %#x\n", (unsigned int)flayer);
1061 oldlay = flayer;
1062 if (oldlay->l_data)
1063 free(oldlay->l_data);
1065 p = Layer2Window(flayer);
1067 flayer = oldlay->l_next;
1068 if (flayer->l_layfn == &WinLf)
1070 if (oldlay->l_blocking)
1072 ASSERT(p->w_blocked > 0);
1073 p->w_blocked--;
1074 debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked);
1076 /* don't warp dead layers: check cvlist */
1077 if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist)
1079 debug("warping to top of blocking chain!\n");
1080 /* warp ourself into savelayer */
1081 flayer = p->w_savelayer;
1082 doredisplay = 1;
1085 if (p && p->w_savelayer == oldlay)
1086 p->w_savelayer = flayer;
1087 #ifdef COPY_PASTE
1088 if (p && oldlay == p->w_paster.pa_pastelayer)
1089 p->w_paster.pa_pastelayer = 0;
1090 #endif
1092 for (lay = layouts; lay; lay = lay->lay_next)
1093 for (cv = lay->lay_cvlist; cv; cv = cv->c_next)
1094 if (cv->c_layer == oldlay)
1095 cv->c_layer = flayer;
1097 /* add all canvases back into next layer's canvas list */
1098 for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext)
1100 cv->c_layer = flayer;
1101 ocv = cv;
1103 if (ocv)
1105 cv = flayer->l_cvlist;
1106 ocv->c_lnext = 0;
1107 flayer->l_cvlist = oldlay->l_cvlist;
1108 /* redisplay only the warped cvs */
1109 if (doredisplay)
1110 LRefreshAll(flayer, 0);
1111 ocv->c_lnext = cv;
1113 oldlay->l_cvlist = 0;
1114 free((char *)oldlay);
1115 LayRestore();
1116 LaySetCursor();