Start converting to GPL v3+ (ref: ticket #23900)
[screen-lua.git] / src / layer.c
blobd80830c98cb9bd214fa3bc1ae137be841de1bf71
1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, see
18 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 ****************************************************************
24 #include <sys/types.h>
26 #include "config.h"
27 #include "screen.h"
28 #include "mark.h"
29 #include "extern.h"
30 #include "braille.h"
32 extern struct display *display, *displays;
34 extern struct mline mline_blank, mline_null;
35 extern struct mchar mchar_blank, mchar_null;
37 extern struct layer *flayer; /* sigh */
38 extern struct LayFuncs WinLf;
39 extern struct LayFuncs BlankLf;
42 static struct mline *mloff __P((struct mline *, int));
45 * Layer subsystem.
47 * ...here is all the clipping code... beware!
49 * XXX: add some speedup code!
53 static struct mline *
54 mloff(ml, off)
55 struct mline *ml;
56 int off;
58 static struct mline mml;
60 if (ml == 0)
61 return 0;
62 mml.image = ml->image + off;
63 mml.attr = ml->attr + off;
64 #ifdef FONT
65 mml.font = ml->font + off;
66 #endif
67 #ifdef COLOR
68 mml.color = ml->color + off;
69 # ifdef COLORS256
70 mml.colorx = ml->colorx + off;
71 # endif
72 #endif
73 return &mml;
76 #ifdef UTF8
77 # define RECODE_MCHAR(mc) ((l->l_encoding == UTF8) != (D_encoding == UTF8) ? recode_mchar(mc, l->l_encoding, D_encoding) : (mc))
78 # define RECODE_MLINE(ml) ((l->l_encoding == UTF8) != (D_encoding == UTF8) ? recode_mline(ml, l->l_width, l->l_encoding, D_encoding) : (ml))
79 #else
80 # define RECODE_MCHAR(mc) (mc)
81 # define RECODE_MLINE(ml) (ml)
82 #endif
85 void
86 LGotoPos(l, x, y)
87 struct layer *l;
88 int x, y;
90 struct canvas *cv;
91 struct viewport *vp;
92 int x2, y2;
94 #ifdef HAVE_BRAILLE
95 if (bd.bd_refreshing)
96 return;
97 #endif
98 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
100 display = cv->c_display;
101 if (D_blocked)
102 continue;
103 if (cv != D_forecv)
104 continue;
105 x2 = x + cv->c_xoff;
106 y2 = y + cv->c_yoff;
107 debug2("---LGotoPos %d %d\n", x2, y2);
108 if (x2 < cv->c_xs)
109 x2 = cv->c_xs;
110 if (y2 < cv->c_ys)
111 y2 = cv->c_ys;
112 if (x2 > cv->c_xe)
113 x2 = cv->c_xe;
114 if (y2 > cv->c_ye)
115 y2 = cv->c_ye;
116 for (vp = cv->c_vplist; vp; vp = vp->v_next)
118 if (x2 < vp->v_xs || x2 > vp->v_xe)
119 continue;
120 if (y2 < vp->v_ys || y2 > vp->v_ye)
121 continue;
122 GotoPos(x2, y2);
123 break;
128 void
129 LScrollH(l, n, y, xs, xe, bce, ol)
130 struct layer *l;
131 int n, y, xs, xe;
132 int bce;
133 struct mline *ol;
135 struct canvas *cv;
136 struct viewport *vp;
137 int y2, xs2, xe2;
139 if (n == 0)
140 return;
141 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
142 for (vp = cv->c_vplist; vp; vp = vp->v_next)
144 y2 = y + vp->v_yoff;
145 if (y2 < vp->v_ys || y2 > vp->v_ye)
146 continue;
147 xs2 = xs + vp->v_xoff;
148 xe2 = xe + vp->v_xoff;
149 if (xs2 < vp->v_xs)
150 xs2 = vp->v_xs;
151 if (xe2 > vp->v_xe)
152 xe2 = vp->v_xe;
153 if (xs2 > xe2)
154 continue;
155 display = cv->c_display;
156 if (D_blocked)
157 continue;
158 ScrollH(y2, xs2, xe2, n, bce, ol ? mloff(ol, -vp->v_xoff) : 0);
159 if (xe2 - xs2 == xe - xs)
160 continue;
161 if (n > 0)
163 xs2 = xe2 + 1 - n;
164 xe2 = xe + vp->v_xoff - n;
166 else
168 xe2 = xs2 - 1 - n;
169 xs2 = xs + vp->v_xoff - n;
171 if (xs2 < vp->v_xs)
172 xs2 = vp->v_xs;
173 if (xe2 > vp->v_xe)
174 xe2 = vp->v_xe;
175 if (xs2 <= xe2)
176 RefreshArea(xs2, y2, xe2, y2, 1);
180 void
181 LScrollV(l, n, ys, ye, bce)
182 struct layer *l;
183 int n;
184 int ys, ye;
185 int bce;
187 struct canvas *cv;
188 struct viewport *vp;
189 int ys2, ye2, xs2, xe2;
190 if (n == 0)
191 return;
192 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
193 for (vp = cv->c_vplist; vp; vp = vp->v_next)
195 xs2 = vp->v_xoff;
196 xe2 = l->l_width - 1 + vp->v_xoff;
197 ys2 = ys + vp->v_yoff;
198 ye2 = ye + vp->v_yoff;
199 if (xs2 < vp->v_xs)
200 xs2 = vp->v_xs;
201 if (xe2 > vp->v_xe)
202 xe2 = vp->v_xe;
203 if (ys2 < vp->v_ys)
204 ys2 = vp->v_ys;
205 if (ye2 > vp->v_ye)
206 ye2 = vp->v_ye;
207 if (ys2 > ye2 || xs2 > xe2)
208 continue;
209 display = cv->c_display;
210 if (D_blocked)
211 continue;
212 #if 0
213 ScrollV(xs2, ys2, xe2, ye2, n, bce);
214 #else
215 ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n, bce);
216 #endif
217 debug2("LScrollV: %d %d", ys, ye);
218 debug2(" -> %d %d\n", ys2, ye2);
219 if (ye2 - ys2 == ye - ys)
220 continue;
221 if (n > 0)
223 ys2 = ye2 + 1 - n;
224 ye2 = ye + vp->v_yoff - n;
226 else
228 ye2 = ys2 - 1 - n;
229 ys2 = ys + vp->v_yoff - n;
231 debug2("LScrollV: - %d %d\n", ys2, ye2);
232 if (ys2 < vp->v_ys)
233 ys2 = vp->v_ys;
234 if (ye2 > vp->v_ye)
235 ye2 = vp->v_ye;
236 debug2("LScrollV: - %d %d\n", ys2, ye2);
237 if (ys2 <= ye2)
238 RefreshArea(xs2, ys2, xe2, ye2, 1);
242 void
243 LInsChar(l, c, x, y, ol)
244 struct layer *l;
245 struct mchar *c;
246 int x, y;
247 struct mline *ol;
249 struct canvas *cv;
250 struct viewport *vp;
251 int xs2, xe2, y2, f;
252 struct mchar *c2, cc;
253 struct mline *rol;
255 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
256 for (vp = cv->c_vplist; vp; vp = vp->v_next)
258 y2 = y + vp->v_yoff;
259 if (y2 < vp->v_ys || y2 > vp->v_ye)
260 continue;
261 xs2 = x + vp->v_xoff;
262 xe2 = l->l_width - 1 + vp->v_xoff;
263 c2 = c;
264 f = 0;
265 if (xs2 < vp->v_xs)
267 xs2 = vp->v_xs;
268 c2 = &mchar_blank;
269 if (ol)
271 int i;
272 i = xs2 - vp->v_xoff - 1;
273 if (i >= 0 && i < l->l_width)
275 copy_mline2mchar(&cc, ol, i);
276 c2 = &cc;
279 else
280 f = 1;
282 if (xe2 > vp->v_xe)
283 xe2 = vp->v_xe;
284 if (xs2 > xe2)
285 continue;
286 display = cv->c_display;
287 if (D_blocked)
288 continue;
289 rol = RECODE_MLINE(ol);
290 InsChar(RECODE_MCHAR(c2), xs2, xe2, y2, mloff(rol, -vp->v_xoff));
291 if (f)
292 RefreshArea(xs2, y2, xs2, y2, 1);
296 void
297 LPutChar(l, c, x, y)
298 struct layer *l;
299 struct mchar *c;
300 int x, y;
302 struct canvas *cv;
303 struct viewport *vp;
304 int x2, y2;
305 #ifdef HAVE_BRAILLE
306 if (bd.bd_refreshing)
308 BPutChar(l, c, x, y);
309 return;
311 #endif
312 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
314 display = cv->c_display;
315 if (D_blocked)
316 continue;
317 for (vp = cv->c_vplist; vp; vp = vp->v_next)
319 y2 = y + vp->v_yoff;
320 if (y2 < vp->v_ys || y2 > vp->v_ye)
321 continue;
322 x2 = x + vp->v_xoff;
323 if (x2 < vp->v_xs || x2 > vp->v_xe)
324 continue;
325 PutChar(RECODE_MCHAR(c), x2, y2);
326 break;
331 void
332 LPutStr(l, s, n, r, x, y)
333 struct layer *l;
334 char *s;
335 int n;
336 struct mchar *r;
337 int x, y;
339 struct canvas *cv;
340 struct viewport *vp;
341 char *s2;
342 int xs2, xe2, y2;
344 if (x + n > l->l_width)
345 n = l->l_width - x;
346 #ifdef HAVE_BRAILLE
347 if (bd.bd_refreshing)
349 BPutStr(l, s, n, r, x, y);
350 return;
352 #endif
353 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
354 for (vp = cv->c_vplist; vp; vp = vp->v_next)
356 y2 = y + vp->v_yoff;
357 if (y2 < vp->v_ys || y2 > vp->v_ye)
358 continue;
359 xs2 = x + vp->v_xoff;
360 xe2 = xs2 + n - 1;
361 if (xs2 < vp->v_xs)
362 xs2 = vp->v_xs;
363 if (xe2 > vp->v_xe)
364 xe2 = vp->v_xe;
365 if (xs2 > xe2)
366 continue;
367 display = cv->c_display;
368 if (D_blocked)
369 continue;
370 GotoPos(xs2, y2);
371 SetRendition(r);
372 s2 = s + xs2 - x - vp->v_xoff;
373 #ifdef UTF8
374 if (D_encoding == UTF8 && l->l_encoding != UTF8 && (r->font || l->l_encoding))
376 struct mchar mc;
377 mc = *r;
378 while (xs2 <= xe2)
380 mc.image = *s2++;
381 PutChar(RECODE_MCHAR(&mc), xs2++, y2);
383 continue;
385 #endif
386 while (xs2++ <= xe2)
387 PUTCHARLP(*s2++);
391 void
392 LPutWinMsg(l, s, n, r, x, y)
393 struct layer *l;
394 char *s;
395 int n;
396 struct mchar *r;
397 int x, y;
399 struct canvas *cv;
400 struct viewport *vp;
401 int xs2, xe2, y2, len, len2;
402 struct mchar or;
404 if (x + n > l->l_width)
405 n = l->l_width - x;
406 #ifdef HAVE_BRAILLE
407 if (bd.bd_refreshing)
409 BPutStr(l, s, n, r, x, y);
410 return;
412 #endif
413 len = strlen(s);
414 if (len > n)
415 len = n;
416 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
417 for (vp = cv->c_vplist; vp; vp = vp->v_next)
419 y2 = y + vp->v_yoff;
420 if (y2 < vp->v_ys || y2 > vp->v_ye)
421 continue;
422 xs2 = x + vp->v_xoff;
423 xe2 = xs2 + n - 1;
424 if (xs2 < vp->v_xs)
425 xs2 = vp->v_xs;
426 if (xe2 > vp->v_xe)
427 xe2 = vp->v_xe;
428 if (xs2 > xe2)
429 continue;
430 display = cv->c_display;
431 if (D_blocked)
432 continue;
433 GotoPos(xs2, y2);
434 SetRendition(r);
435 len2 = xe2 - (x + vp->v_xoff) + 1;
436 if (len2 > len)
437 len2 = len;
438 PutWinMsg(s, xs2 - x - vp->v_xoff, len2);
439 xs2 = x + vp->v_xoff + len2;
440 if (xs2 < vp->v_xs)
441 xs2 = vp->v_xs;
442 or = D_rend;
443 GotoPos(xs2, y2);
444 SetRendition(&or);
445 while (xs2++ <= xe2)
446 PUTCHARLP(' ');
450 void
451 LClearLine(l, y, xs, xe, bce, ol)
452 struct layer *l;
453 int xs, xe, bce;
454 struct mline *ol;
456 struct canvas *cv;
457 struct viewport *vp;
458 int y2, xs2, xe2;
460 /* check for magic margin condition */
461 if (xs >= l->l_width)
462 xs = l->l_width - 1;
463 if (xe >= l->l_width)
464 xe = l->l_width - 1;
465 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
466 for (vp = cv->c_vplist; vp; vp = vp->v_next)
468 xs2 = xs + vp->v_xoff;
469 xe2 = xe + vp->v_xoff;
470 y2 = y + vp->v_yoff;
471 if (y2 < vp->v_ys || y2 > vp->v_ye)
472 continue;
473 if (xs2 < vp->v_xs)
474 xs2 = vp->v_xs;
475 if (xe2 > vp->v_xe)
476 xe2 = vp->v_xe;
477 if (xs2 > xe2)
478 continue;
479 display = cv->c_display;
480 if (D_blocked)
481 continue;
482 ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
486 void
487 LClearArea(l, xs, ys, xe, ye, bce, uself)
488 struct layer *l;
489 int xs, ys, xe, ye;
490 int bce;
491 int uself;
493 struct canvas *cv;
494 struct viewport *vp;
495 int xs2, ys2, xe2, ye2;
496 #ifdef HAVE_BRAILLE
497 if (bd.bd_refreshing)
498 return;
499 #endif
500 /* check for magic margin condition */
501 if (xs >= l->l_width)
502 xs = l->l_width - 1;
503 if (xe >= l->l_width)
504 xe = l->l_width - 1;
505 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
507 display = cv->c_display;
508 if (D_blocked)
509 continue;
510 for (vp = cv->c_vplist; vp; vp = vp->v_next)
512 xs2 = xs + vp->v_xoff;
513 xe2 = xe + vp->v_xoff;
514 ys2 = ys + vp->v_yoff;
515 ye2 = ye + vp->v_yoff;
516 if (xs2 < vp->v_xs)
517 xs2 = vp->v_xs;
518 if (xe2 > vp->v_xe)
519 xe2 = vp->v_xe;
520 if (xs2 > vp->v_xe)
521 ys2++;
522 if (xe2 < vp->v_xs)
523 ye2--;
524 if (ys2 < vp->v_ys)
525 ys2 = vp->v_ys;
526 if (ye2 > vp->v_ye)
527 ye2 = vp->v_ye;
528 if (ys2 > ye2)
529 continue;
530 #if 0
531 xcs = vp->v_xoff;
532 xce = l->l_width - 1 + vp->v_xoff;
533 if (xcs < vp->v_xs)
534 xcs = vp->v_xs;
535 if (xce > vp->v_xe)
536 xce = vp->v_xe;
537 if (xcs > xce)
538 continue;
539 if (ys2 != ys + vp->v_yoff)
540 xs2 = xcs;
541 if (ye2 != ye + vp->v_yoff)
542 xe2 = xce;
543 display = cv->c_display;
544 ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself);
545 #else
546 if (xs == 0 || ys2 != ys + vp->v_yoff)
547 xs2 = vp->v_xs;
548 if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
549 xe2 = vp->v_xe;
550 display = cv->c_display;
551 ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself);
552 #endif
557 void
558 LCDisplayLine(l, ml, y, xs, xe, isblank)
559 struct layer *l;
560 struct mline *ml;
561 int y, xs, xe;
562 int isblank;
564 struct canvas *cv;
565 struct viewport *vp;
566 int xs2, xe2, y2;
567 #ifdef HAVE_BRAILLE
568 if (bd.bd_refreshing)
570 BCDisplayLine(l, ml, y, xs, xe, isblank);
571 return;
573 #endif
574 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
576 display = cv->c_display;
577 if (D_blocked)
578 continue;
579 for (vp = cv->c_vplist; vp; vp = vp->v_next)
581 xs2 = xs + vp->v_xoff;
582 xe2 = xe + vp->v_xoff;
583 y2 = y + vp->v_yoff;
584 if (y2 < vp->v_ys || y2 > vp->v_ye)
585 continue;
586 if (xs2 < vp->v_xs)
587 xs2 = vp->v_xs;
588 if (xe2 > vp->v_xe)
589 xe2 = vp->v_xe;
590 if (xs2 > xe2)
591 continue;
592 display = cv->c_display;
593 debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
594 debug1(" mloff = %d\n", -vp->v_xoff);
595 DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
600 void
601 LCDisplayLineWrap(l, ml, y, from, to, isblank)
602 struct layer *l;
603 struct mline *ml;
604 int y, from, to;
605 int isblank;
607 struct mchar nc;
608 copy_mline2mchar(&nc, ml, 0);
609 #ifdef DW_CHARS
610 if (dw_left(ml, 0, l->l_encoding))
612 nc.mbcs = ml->image[1];
613 from++;
615 #endif
616 LWrapChar(l, &nc, y - 1, -1, -1, 0);
617 from++;
618 if (from <= to)
619 LCDisplayLine(l, ml, y, from, to, isblank);
622 void
623 LSetRendition(l, r)
624 struct layer *l;
625 struct mchar *r;
627 struct canvas *cv;
629 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
631 display = cv->c_display;
632 if (D_blocked)
633 continue;
634 SetRendition(r);
638 void
639 LWrapChar(l, c, y, top, bot, ins)
640 struct layer *l;
641 struct mchar *c;
642 int y, top, bot;
643 int ins;
645 struct canvas *cv, *cvlist, *cvlnext;
646 struct viewport *vp, *evp, **vpp;
647 int yy, y2, yy2, top2, bot2;
648 int bce;
650 #ifdef COLOR
651 bce = rend_getbg(c);
652 #else
653 bce = 0;
654 #endif
655 if (y != bot)
657 /* simple case: no scrolling */
659 /* cursor after wrapping */
660 yy = y == l->l_height - 1 ? y : y + 1;
662 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
664 y2 = 0; /* gcc -Wall */
665 display = cv->c_display;
666 if (D_blocked)
667 continue;
668 /* find the viewport of the wrapped character */
669 for (vp = cv->c_vplist; vp; vp = vp->v_next)
671 y2 = y + vp->v_yoff;
672 yy2 = yy + vp->v_yoff;
673 if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
674 break;
676 if (vp == 0)
677 continue; /* nothing to do, character not visible */
678 /* find the viewport of the character at the end of the line*/
679 for (evp = cv->c_vplist; evp; evp = evp->v_next)
680 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)
681 break; /* gotcha! */
682 if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye))
684 /* no wrapping possible */
685 debug("LWrap: can't wrap!\n");
686 cvlist = l->l_cvlist;
687 cvlnext = cv->c_lnext;
688 l->l_cvlist = cv;
689 cv->c_lnext = 0;
690 if (ins)
691 LInsChar(l, c, 0, yy, 0);
692 else
693 LPutChar(l, c, 0, yy);
694 l->l_cvlist = cvlist;
695 cv->c_lnext = cvlnext;
697 else
699 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
703 else
705 /* hard case: scroll up*/
707 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
709 display = cv->c_display;
710 if (D_blocked)
711 continue;
712 /* search for wrap viewport */
713 for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next)
715 yy2 = bot + vp->v_yoff;
716 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)
717 break;
720 if (vp)
722 /* great, can use Wrap on the vp */
723 /* temporarily remove vp from cvlist */
724 *vpp = vp->v_next;
726 if (cv->c_vplist)
728 /* scroll all viewports != vp */
729 cvlist = l->l_cvlist;
730 cvlnext = cv->c_lnext;
731 l->l_cvlist = cv;
732 cv->c_lnext = 0;
733 LScrollV(l, 1, top, bot, bce);
734 if (!vp)
736 if (ins)
737 LInsChar(l, c, 0, bot, 0);
738 else
739 LPutChar(l, c, 0, bot);
741 l->l_cvlist = cvlist;
742 cv->c_lnext = cvlnext;
744 if (vp)
746 /* add vp back to cvlist */
747 *vpp = vp;
748 top2 = top + vp->v_yoff;
749 bot2 = bot + vp->v_yoff;
750 if (top2 < vp->v_ys)
751 top2 = vp->v_ys;
752 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
759 void
760 LCursorVisibility(l, vis)
761 struct layer *l;
762 int vis;
764 struct canvas *cv;
765 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
767 display = cv->c_display;
768 if (D_blocked)
769 continue;
770 if (cv != D_forecv)
771 continue;
772 CursorVisibility(vis);
776 void
777 LSetFlow(l, flow)
778 struct layer *l;
779 int flow;
781 struct canvas *cv;
782 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
784 display = cv->c_display;
785 if (cv != D_forecv)
786 continue;
787 SetFlow(flow);
791 void
792 LKeypadMode(l, on)
793 struct layer *l;
794 int on;
796 struct canvas *cv;
797 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
799 display = cv->c_display;
800 if (D_blocked)
801 continue;
802 if (cv != D_forecv)
803 continue;
804 KeypadMode(on);
808 void
809 LCursorkeysMode(l, on)
810 struct layer *l;
811 int on;
813 struct canvas *cv;
814 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
816 display = cv->c_display;
817 if (D_blocked)
818 continue;
819 if (cv != D_forecv)
820 continue;
821 CursorkeysMode(on);
825 void
826 LMouseMode(l, on)
827 struct layer *l;
828 int on;
830 struct canvas *cv;
831 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
833 display = cv->c_display;
834 if (D_blocked)
835 continue;
836 if (cv != D_forecv)
837 continue;
838 MouseMode(on);
842 void
843 LClearAll(l, uself)
844 struct layer *l;
845 int uself;
847 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
850 void
851 LRefreshAll(l, isblank)
852 struct layer *l;
853 int isblank;
855 struct layer *oldflayer;
856 int y;
858 debug1("LRefreshAll isblank=%d\n", isblank);
859 oldflayer = flayer;
860 flayer = l;
861 if (!isblank)
862 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0);
863 /* signal full refresh */
864 LayRedisplayLine(-1, -1, -1, 1);
865 for (y = 0; y < l->l_height; y++)
866 LayRedisplayLine(y, 0, l->l_width - 1, 1);
867 flayer = oldflayer;
870 void
871 /*VARARGS2*/
872 #if defined(USEVARARGS) && defined(__STDC__)
873 LMsg(int err, char *fmt, VA_DOTS)
874 #else
875 LMsg(err, fmt, VA_DOTS)
876 int err;
877 char *fmt;
878 VA_DECL
879 #endif
881 VA_LIST(ap)
882 char buf[MAXPATHLEN*2];
883 char *p = buf;
884 struct canvas *cv;
886 VA_START(ap, fmt);
887 fmt = DoNLS(fmt);
888 (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
889 VA_END(ap);
890 if (err)
892 p += strlen(p);
893 *p++ = ':';
894 *p++ = ' ';
895 strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
896 buf[sizeof(buf) - 1] = 0;
898 debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
899 for (display = displays; display; display = display->d_next)
901 for (cv = D_cvlist; cv; cv = cv->c_next)
902 if (cv->c_layer == flayer)
903 break;
904 if (cv == 0)
905 continue;
906 MakeStatus(buf);
911 /*******************************************************************/
912 /*******************************************************************/
915 * Layer creation / removal
918 void
919 KillLayerChain(lay)
920 struct layer *lay;
922 struct canvas *cv, *ncv;
923 struct layer *l, *oldflayer;
925 oldflayer = flayer;
926 debug1("KillLayerChain %#x\n", lay);
927 for (l = lay; l; l = l->l_next)
929 if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
930 break;
931 debug1("- killing %#x\n", l);
932 if (oldflayer == l)
933 oldflayer = 0;
934 for (cv = l->l_cvlist; cv; cv = ncv)
936 ncv = cv->c_lnext;
937 cv->c_layer = 0;
938 cv->c_lnext = 0;
941 flayer = lay;
942 while (flayer != l)
943 ExitOverlayPage();
944 flayer = oldflayer;
950 InitOverlayPage(datasize, lf, block)
951 int datasize;
952 struct LayFuncs *lf;
953 int block;
955 char *data;
956 struct layer *newlay;
957 struct canvas *cv, *cvp, **cvpp;
958 struct win *p;
960 ASSERT(flayer);
962 cv = 0;
963 if (display && D_forecv->c_layer == flayer)
964 cv = D_forecv; /* work only on this cv! */
966 if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0)
968 Msg(0, "No memory for layer struct");
969 return -1;
971 debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
972 data = 0;
973 if (datasize)
975 if ((data = malloc(datasize)) == 0)
977 free((char *)newlay);
978 Msg(0, "No memory for layer data");
979 return -1;
981 bzero(data, datasize);
984 p = Layer2Window(flayer);
986 if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0)))
988 if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0)
989 KillLayerChain(p->w_savelayer);
990 p->w_savelayer = newlay;
993 if (cv && flayer->l_next == 0 && !block)
995 struct display *olddisplay = display;
996 display = cv->c_display;
997 RemoveStatus();
998 display = olddisplay;
1000 /* new branch -> just get canvas vps */
1001 for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
1002 if (cvp == cv)
1003 break;
1004 ASSERT(cvp);
1005 *cvpp = cv->c_lnext;
1006 newlay->l_cvlist = cv;
1007 cv->c_lnext = 0;
1008 cv->c_layer = newlay;
1010 else
1012 LAY_DISPLAYS(flayer, RemoveStatus());
1013 if (block)
1014 debug("layer is blocking\n");
1015 if (block && flayer->l_layfn == &WinLf)
1017 debug("...and is first, so window gets blocked\n");
1018 ASSERT(p->w_blocked == 0);
1019 p->w_blocked++;
1020 newlay->l_blocking = 1;
1022 /* change all canvases */
1023 newlay->l_cvlist = flayer->l_cvlist;
1024 for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
1025 cvp->c_layer = newlay;
1026 flayer->l_cvlist = 0;
1028 newlay->l_width = flayer->l_width;
1029 newlay->l_height = flayer->l_height;
1030 newlay->l_encoding = 0;
1031 newlay->l_layfn = lf;
1032 newlay->l_data = data;
1033 newlay->l_next = flayer;
1034 newlay->l_bottom = flayer->l_bottom;
1035 flayer = newlay;
1036 LayRestore();
1037 return 0;
1040 extern struct layout *layouts;
1042 void
1043 ExitOverlayPage()
1045 struct layer *oldlay;
1046 struct win *p;
1047 int doredisplay = 0;
1048 struct canvas *cv, *ocv;
1049 struct layout *lay;
1051 ASSERT(flayer);
1052 debug1("Exiting layer %#x\n", (unsigned int)flayer);
1053 oldlay = flayer;
1054 if (oldlay->l_data)
1055 free(oldlay->l_data);
1057 p = Layer2Window(flayer);
1059 flayer = oldlay->l_next;
1060 if (flayer->l_layfn == &WinLf)
1062 if (oldlay->l_blocking)
1064 ASSERT(p->w_blocked > 0);
1065 p->w_blocked--;
1066 debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked);
1068 /* don't warp dead layers: check cvlist */
1069 if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist)
1071 debug("warping to top of blocking chain!\n");
1072 /* warp ourself into savelayer */
1073 flayer = p->w_savelayer;
1074 doredisplay = 1;
1077 if (p && p->w_savelayer == oldlay)
1078 p->w_savelayer = flayer;
1079 #ifdef COPY_PASTE
1080 if (p && oldlay == p->w_paster.pa_pastelayer)
1081 p->w_paster.pa_pastelayer = 0;
1082 #endif
1084 for (lay = layouts; lay; lay = lay->lay_next)
1085 for (cv = lay->lay_cvlist; cv; cv = cv->c_next)
1086 if (cv->c_layer == oldlay)
1087 cv->c_layer = flayer;
1089 /* add all canvases back into next layer's canvas list */
1090 for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext)
1092 cv->c_layer = flayer;
1093 ocv = cv;
1095 if (ocv)
1097 cv = flayer->l_cvlist;
1098 ocv->c_lnext = 0;
1099 flayer->l_cvlist = oldlay->l_cvlist;
1100 /* redisplay only the warped cvs */
1101 if (doredisplay)
1102 LRefreshAll(flayer, 0);
1103 ocv->c_lnext = cv;
1105 oldlay->l_cvlist = 0;
1106 free((char *)oldlay);
1107 LayRestore();
1108 LaySetCursor();