Sanity check line numbers for non-negative value.
[screen-lua.git] / src / layer.c
blob9c1fe34b06efdc1cb0d1636c1f3f7d08b1878e31
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 if (l->l_pause.d)
101 LayPauseUpdateRegion(l, x, x, y, y);
102 return;
105 #ifdef HAVE_BRAILLE
106 if (bd.bd_refreshing)
107 return;
108 #endif
109 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
111 display = cv->c_display;
112 if (D_blocked)
113 continue;
114 if (cv != D_forecv)
115 continue;
116 x2 = x + cv->c_xoff;
117 y2 = y + cv->c_yoff;
118 debug2("---LGotoPos %d %d\n", x2, y2);
119 if (x2 < cv->c_xs)
120 x2 = cv->c_xs;
121 if (y2 < cv->c_ys)
122 y2 = cv->c_ys;
123 if (x2 > cv->c_xe)
124 x2 = cv->c_xe;
125 if (y2 > cv->c_ye)
126 y2 = cv->c_ye;
127 for (vp = cv->c_vplist; vp; vp = vp->v_next)
129 if (x2 < vp->v_xs || x2 > vp->v_xe)
130 continue;
131 if (y2 < vp->v_ys || y2 > vp->v_ye)
132 continue;
133 GotoPos(x2, y2);
134 break;
139 void
140 LScrollH(l, n, y, xs, xe, bce, ol)
141 struct layer *l;
142 int n, y, xs, xe;
143 int bce;
144 struct mline *ol;
146 struct canvas *cv;
147 struct viewport *vp;
148 int y2, xs2, xe2;
150 if (n == 0)
151 return;
152 if (l->l_pause.d)
154 LayPauseUpdateRegion(l, xs, xe, y, y);
155 return;
157 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
158 for (vp = cv->c_vplist; vp; vp = vp->v_next)
160 y2 = y + vp->v_yoff;
161 if (y2 < vp->v_ys || y2 > vp->v_ye)
162 continue;
163 xs2 = xs + vp->v_xoff;
164 xe2 = xe + vp->v_xoff;
165 if (xs2 < vp->v_xs)
166 xs2 = vp->v_xs;
167 if (xe2 > vp->v_xe)
168 xe2 = vp->v_xe;
169 if (xs2 > xe2)
170 continue;
171 display = cv->c_display;
172 if (D_blocked)
173 continue;
174 ScrollH(y2, xs2, xe2, n, bce, ol ? mloff(ol, -vp->v_xoff) : 0);
175 if (xe2 - xs2 == xe - xs)
176 continue;
177 if (n > 0)
179 xs2 = xe2 + 1 - n;
180 xe2 = xe + vp->v_xoff - n;
182 else
184 xe2 = xs2 - 1 - n;
185 xs2 = xs + vp->v_xoff - n;
187 if (xs2 < vp->v_xs)
188 xs2 = vp->v_xs;
189 if (xe2 > vp->v_xe)
190 xe2 = vp->v_xe;
191 if (xs2 <= xe2)
192 RefreshArea(xs2, y2, xe2, y2, 1);
196 void
197 LScrollV(l, n, ys, ye, bce)
198 struct layer *l;
199 int n;
200 int ys, ye;
201 int bce;
203 struct canvas *cv;
204 struct viewport *vp;
205 int ys2, ye2, xs2, xe2;
206 if (n == 0)
207 return;
208 if (l->l_pause.d)
210 LayPauseUpdateRegion(l, 0, l->l_width - 1, ys, ye);
211 return;
213 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
214 for (vp = cv->c_vplist; vp; vp = vp->v_next)
216 xs2 = vp->v_xoff;
217 xe2 = l->l_width - 1 + vp->v_xoff;
218 ys2 = ys + vp->v_yoff;
219 ye2 = ye + vp->v_yoff;
220 if (xs2 < vp->v_xs)
221 xs2 = vp->v_xs;
222 if (xe2 > vp->v_xe)
223 xe2 = vp->v_xe;
224 if (ys2 < vp->v_ys)
225 ys2 = vp->v_ys;
226 if (ye2 > vp->v_ye)
227 ye2 = vp->v_ye;
228 if (ys2 > ye2 || xs2 > xe2)
229 continue;
230 display = cv->c_display;
231 if (D_blocked)
232 continue;
233 #if 0
234 ScrollV(xs2, ys2, xe2, ye2, n, bce);
235 #else
236 ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n, bce);
237 #endif
238 debug2("LScrollV: %d %d", ys, ye);
239 debug2(" -> %d %d\n", ys2, ye2);
240 if (ye2 - ys2 == ye - ys)
241 continue;
242 if (n > 0)
244 ys2 = ye2 + 1 - n;
245 ye2 = ye + vp->v_yoff - n;
247 else
249 ye2 = ys2 - 1 - n;
250 ys2 = ys + vp->v_yoff - n;
252 debug2("LScrollV: - %d %d\n", ys2, ye2);
253 if (ys2 < vp->v_ys)
254 ys2 = vp->v_ys;
255 if (ye2 > vp->v_ye)
256 ye2 = vp->v_ye;
257 debug2("LScrollV: - %d %d\n", ys2, ye2);
258 if (ys2 <= ye2)
259 RefreshArea(xs2, ys2, xe2, ye2, 1);
263 void
264 LInsChar(l, c, x, y, ol)
265 struct layer *l;
266 struct mchar *c;
267 int x, y;
268 struct mline *ol;
270 struct canvas *cv;
271 struct viewport *vp;
272 int xs2, xe2, y2, f;
273 struct mchar *c2, cc;
274 struct mline *rol;
276 if (l->l_pause.d)
278 LayPauseUpdateRegion(l, x, l->l_width - 1, y, y);
279 return;
281 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
282 for (vp = cv->c_vplist; vp; vp = vp->v_next)
284 y2 = y + vp->v_yoff;
285 if (y2 < vp->v_ys || y2 > vp->v_ye)
286 continue;
287 xs2 = x + vp->v_xoff;
288 xe2 = l->l_width - 1 + vp->v_xoff;
289 c2 = c;
290 f = 0;
291 if (xs2 < vp->v_xs)
293 xs2 = vp->v_xs;
294 c2 = &mchar_blank;
295 if (ol)
297 int i;
298 i = xs2 - vp->v_xoff - 1;
299 if (i >= 0 && i < l->l_width)
301 copy_mline2mchar(&cc, ol, i);
302 c2 = &cc;
305 else
306 f = 1;
308 if (xe2 > vp->v_xe)
309 xe2 = vp->v_xe;
310 if (xs2 > xe2)
311 continue;
312 display = cv->c_display;
313 if (D_blocked)
314 continue;
315 rol = RECODE_MLINE(ol);
316 InsChar(RECODE_MCHAR(c2), xs2, xe2, y2, mloff(rol, -vp->v_xoff));
317 if (f)
318 RefreshArea(xs2, y2, xs2, y2, 1);
322 void
323 LPutChar(l, c, x, y)
324 struct layer *l;
325 struct mchar *c;
326 int x, y;
328 struct canvas *cv;
329 struct viewport *vp;
330 int x2, y2;
331 #ifdef HAVE_BRAILLE
332 if (bd.bd_refreshing)
334 BPutChar(l, c, x, y);
335 return;
337 #endif
339 if (l->l_pause.d)
341 LayPauseUpdateRegion(l, x, x, y, y);
342 return;
345 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
347 display = cv->c_display;
348 if (D_blocked)
349 continue;
350 for (vp = cv->c_vplist; vp; vp = vp->v_next)
352 y2 = y + vp->v_yoff;
353 if (y2 < vp->v_ys || y2 > vp->v_ye)
354 continue;
355 x2 = x + vp->v_xoff;
356 if (x2 < vp->v_xs || x2 > vp->v_xe)
357 continue;
358 PutChar(RECODE_MCHAR(c), x2, y2);
359 break;
364 void
365 LPutStr(l, s, n, r, x, y)
366 struct layer *l;
367 char *s;
368 int n;
369 struct mchar *r;
370 int x, y;
372 struct canvas *cv;
373 struct viewport *vp;
374 char *s2;
375 int xs2, xe2, y2;
377 if (x + n > l->l_width)
378 n = l->l_width - x;
379 #ifdef HAVE_BRAILLE
380 if (bd.bd_refreshing)
382 BPutStr(l, s, n, r, x, y);
383 return;
385 #endif
386 if (l->l_pause.d)
388 LayPauseUpdateRegion(l, x, x + n - 1, y, y);
389 return;
392 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
393 for (vp = cv->c_vplist; vp; vp = vp->v_next)
395 y2 = y + vp->v_yoff;
396 if (y2 < vp->v_ys || y2 > vp->v_ye)
397 continue;
398 xs2 = x + vp->v_xoff;
399 xe2 = xs2 + n - 1;
400 if (xs2 < vp->v_xs)
401 xs2 = vp->v_xs;
402 if (xe2 > vp->v_xe)
403 xe2 = vp->v_xe;
404 if (xs2 > xe2)
405 continue;
406 display = cv->c_display;
407 if (D_blocked)
408 continue;
409 GotoPos(xs2, y2);
410 SetRendition(r);
411 s2 = s + xs2 - x - vp->v_xoff;
412 #ifdef UTF8
413 if (D_encoding == UTF8 && l->l_encoding != UTF8 && (r->font || l->l_encoding))
415 struct mchar mc;
416 mc = *r;
417 while (xs2 <= xe2)
419 mc.image = *s2++;
420 PutChar(RECODE_MCHAR(&mc), xs2++, y2);
422 continue;
424 #endif
425 while (xs2++ <= xe2)
426 PUTCHARLP(*s2++);
430 void
431 LPutWinMsg(l, s, n, r, x, y)
432 struct layer *l;
433 char *s;
434 int n;
435 struct mchar *r;
436 int x, y;
438 struct canvas *cv;
439 struct viewport *vp;
440 int xs2, xe2, y2, len, len2;
441 struct mchar or;
443 if (x + n > l->l_width)
444 n = l->l_width - x;
445 #ifdef HAVE_BRAILLE
446 if (bd.bd_refreshing)
448 BPutStr(l, s, n, r, x, y);
449 return;
451 #endif
452 if (l->l_pause.d)
454 LayPauseUpdateRegion(l, x, x + n - 1, y, y);
455 return;
457 len = strlen(s);
458 if (len > n)
459 len = n;
460 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
461 for (vp = cv->c_vplist; vp; vp = vp->v_next)
463 y2 = y + vp->v_yoff;
464 if (y2 < vp->v_ys || y2 > vp->v_ye)
465 continue;
466 xs2 = x + vp->v_xoff;
467 xe2 = xs2 + n - 1;
468 if (xs2 < vp->v_xs)
469 xs2 = vp->v_xs;
470 if (xe2 > vp->v_xe)
471 xe2 = vp->v_xe;
472 if (xs2 > xe2)
473 continue;
474 display = cv->c_display;
475 if (D_blocked)
476 continue;
477 GotoPos(xs2, y2);
478 SetRendition(r);
479 len2 = xe2 - (x + vp->v_xoff) + 1;
480 if (len2 > len)
481 len2 = len;
482 PutWinMsg(s, xs2 - x - vp->v_xoff, len2);
483 xs2 = x + vp->v_xoff + len2;
484 if (xs2 < vp->v_xs)
485 xs2 = vp->v_xs;
486 or = D_rend;
487 GotoPos(xs2, y2);
488 SetRendition(&or);
489 while (xs2++ <= xe2)
490 PUTCHARLP(' ');
494 void
495 LClearLine(l, y, xs, xe, bce, ol)
496 struct layer *l;
497 int xs, xe, bce;
498 struct mline *ol;
500 struct canvas *cv;
501 struct viewport *vp;
502 int y2, xs2, xe2;
504 /* check for magic margin condition */
505 if (xs >= l->l_width)
506 xs = l->l_width - 1;
507 if (xe >= l->l_width)
508 xe = l->l_width - 1;
509 if (l->l_pause.d)
511 LayPauseUpdateRegion(l, xs, xe, y, y);
512 return;
514 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
515 for (vp = cv->c_vplist; vp; vp = vp->v_next)
517 xs2 = xs + vp->v_xoff;
518 xe2 = xe + vp->v_xoff;
519 y2 = y + vp->v_yoff;
520 if (y2 < vp->v_ys || y2 > vp->v_ye)
521 continue;
522 if (xs2 < vp->v_xs)
523 xs2 = vp->v_xs;
524 if (xe2 > vp->v_xe)
525 xe2 = vp->v_xe;
526 if (xs2 > xe2)
527 continue;
528 display = cv->c_display;
529 if (D_blocked)
530 continue;
531 ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
535 void
536 LClearArea(l, xs, ys, xe, ye, bce, uself)
537 struct layer *l;
538 int xs, ys, xe, ye;
539 int bce;
540 int uself;
542 struct canvas *cv;
543 struct viewport *vp;
544 int xs2, ys2, xe2, ye2;
545 #ifdef HAVE_BRAILLE
546 if (bd.bd_refreshing)
547 return;
548 #endif
549 /* Check for zero-height window */
550 if (ys < 0 || ye < ys)
551 return;
553 /* check for magic margin condition */
554 if (xs >= l->l_width)
555 xs = l->l_width - 1;
556 if (xe >= l->l_width)
557 xe = l->l_width - 1;
558 if (l->l_pause.d)
560 LayPauseUpdateRegion(l, xs, xe, ys, ye);
561 return;
563 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
565 display = cv->c_display;
566 if (D_blocked)
567 continue;
568 for (vp = cv->c_vplist; vp; vp = vp->v_next)
570 xs2 = xs + vp->v_xoff;
571 xe2 = xe + vp->v_xoff;
572 ys2 = ys + vp->v_yoff;
573 ye2 = ye + vp->v_yoff;
574 if (xs2 < vp->v_xs)
575 xs2 = vp->v_xs;
576 if (xe2 > vp->v_xe)
577 xe2 = vp->v_xe;
578 if (xs2 > vp->v_xe)
579 ys2++;
580 if (xe2 < vp->v_xs)
581 ye2--;
582 if (ys2 < vp->v_ys)
583 ys2 = vp->v_ys;
584 if (ye2 > vp->v_ye)
585 ye2 = vp->v_ye;
586 if (ys2 > ye2)
587 continue;
588 #if 0
589 xcs = vp->v_xoff;
590 xce = l->l_width - 1 + vp->v_xoff;
591 if (xcs < vp->v_xs)
592 xcs = vp->v_xs;
593 if (xce > vp->v_xe)
594 xce = vp->v_xe;
595 if (xcs > xce)
596 continue;
597 if (ys2 != ys + vp->v_yoff)
598 xs2 = xcs;
599 if (ye2 != ye + vp->v_yoff)
600 xe2 = xce;
601 display = cv->c_display;
602 ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself);
603 #else
604 if (xs == 0 || ys2 != ys + vp->v_yoff)
605 xs2 = vp->v_xs;
606 if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
607 xe2 = vp->v_xe;
608 display = cv->c_display;
609 ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself);
610 #endif
615 void
616 LCDisplayLine(l, ml, y, xs, xe, isblank)
617 struct layer *l;
618 struct mline *ml;
619 int y, xs, xe;
620 int isblank;
622 struct canvas *cv;
623 struct viewport *vp;
624 int xs2, xe2, y2;
625 #ifdef HAVE_BRAILLE
626 if (bd.bd_refreshing)
628 BCDisplayLine(l, ml, y, xs, xe, isblank);
629 return;
631 #endif
632 if (l->l_pause.d)
634 LayPauseUpdateRegion(l, xs, xe, y, y);
635 return;
637 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
639 display = cv->c_display;
640 if (D_blocked)
641 continue;
642 for (vp = cv->c_vplist; vp; vp = vp->v_next)
644 xs2 = xs + vp->v_xoff;
645 xe2 = xe + vp->v_xoff;
646 y2 = y + vp->v_yoff;
647 if (y2 < vp->v_ys || y2 > vp->v_ye)
648 continue;
649 if (xs2 < vp->v_xs)
650 xs2 = vp->v_xs;
651 if (xe2 > vp->v_xe)
652 xe2 = vp->v_xe;
653 if (xs2 > xe2)
654 continue;
655 display = cv->c_display;
656 debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
657 debug1(" mloff = %d\n", -vp->v_xoff);
658 DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
663 void
664 LCDisplayLineWrap(l, ml, y, from, to, isblank)
665 struct layer *l;
666 struct mline *ml;
667 int y, from, to;
668 int isblank;
670 struct mchar nc;
671 copy_mline2mchar(&nc, ml, 0);
672 #ifdef DW_CHARS
673 if (dw_left(ml, 0, l->l_encoding))
675 nc.mbcs = ml->image[1];
676 from++;
678 #endif
679 LWrapChar(l, &nc, y - 1, -1, -1, 0);
680 from++;
681 if (from <= to)
682 LCDisplayLine(l, ml, y, from, to, isblank);
685 void
686 LSetRendition(l, r)
687 struct layer *l;
688 struct mchar *r;
690 struct canvas *cv;
692 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
694 display = cv->c_display;
695 if (D_blocked)
696 continue;
697 SetRendition(r);
701 void
702 LWrapChar(l, c, y, top, bot, ins)
703 struct layer *l;
704 struct mchar *c;
705 int y, top, bot;
706 int ins;
708 struct canvas *cv, *cvlist, *cvlnext;
709 struct viewport *vp, *evp, **vpp;
710 int yy, y2, yy2, top2, bot2;
711 int bce;
713 if (l->l_pause.d)
715 /* XXX: 'y'? */
716 LayPauseUpdateRegion(l, 0, l->l_width - 1, top, bot);
717 return;
720 #ifdef COLOR
721 bce = rend_getbg(c);
722 #else
723 bce = 0;
724 #endif
725 if (y != bot)
727 /* simple case: no scrolling */
729 /* cursor after wrapping */
730 yy = y == l->l_height - 1 ? y : y + 1;
732 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
734 y2 = 0; /* gcc -Wall */
735 display = cv->c_display;
736 if (D_blocked)
737 continue;
738 /* find the viewport of the wrapped character */
739 for (vp = cv->c_vplist; vp; vp = vp->v_next)
741 y2 = y + vp->v_yoff;
742 yy2 = yy + vp->v_yoff;
743 if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
744 break;
746 if (vp == 0)
747 continue; /* nothing to do, character not visible */
748 /* find the viewport of the character at the end of the line*/
749 for (evp = cv->c_vplist; evp; evp = evp->v_next)
750 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)
751 break; /* gotcha! */
752 if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye))
754 /* no wrapping possible */
755 debug("LWrap: can't wrap!\n");
756 cvlist = l->l_cvlist;
757 cvlnext = cv->c_lnext;
758 l->l_cvlist = cv;
759 cv->c_lnext = 0;
760 if (ins)
761 LInsChar(l, c, 0, yy, 0);
762 else
763 LPutChar(l, c, 0, yy);
764 l->l_cvlist = cvlist;
765 cv->c_lnext = cvlnext;
767 else
769 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
773 else
775 /* hard case: scroll up*/
777 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
779 display = cv->c_display;
780 if (D_blocked)
781 continue;
782 /* search for wrap viewport */
783 for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next)
785 yy2 = bot + vp->v_yoff;
786 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)
787 break;
790 if (vp)
792 /* great, can use Wrap on the vp */
793 /* temporarily remove vp from cvlist */
794 *vpp = vp->v_next;
796 if (cv->c_vplist)
798 /* scroll all viewports != vp */
799 cvlist = l->l_cvlist;
800 cvlnext = cv->c_lnext;
801 l->l_cvlist = cv;
802 cv->c_lnext = 0;
803 LScrollV(l, 1, top, bot, bce);
804 if (!vp)
806 if (ins)
807 LInsChar(l, c, 0, bot, 0);
808 else
809 LPutChar(l, c, 0, bot);
811 l->l_cvlist = cvlist;
812 cv->c_lnext = cvlnext;
814 if (vp)
816 /* add vp back to cvlist */
817 *vpp = vp;
818 top2 = top + vp->v_yoff;
819 bot2 = bot + vp->v_yoff;
820 if (top2 < vp->v_ys)
821 top2 = vp->v_ys;
822 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
829 void
830 LCursorVisibility(l, vis)
831 struct layer *l;
832 int vis;
834 struct canvas *cv;
835 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
837 display = cv->c_display;
838 if (D_blocked)
839 continue;
840 if (cv != D_forecv)
841 continue;
842 CursorVisibility(vis);
846 void
847 LSetFlow(l, flow)
848 struct layer *l;
849 int flow;
851 struct canvas *cv;
852 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
854 display = cv->c_display;
855 if (cv != D_forecv)
856 continue;
857 SetFlow(flow);
861 void
862 LKeypadMode(l, on)
863 struct layer *l;
864 int on;
866 struct canvas *cv;
867 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
869 display = cv->c_display;
870 if (D_blocked)
871 continue;
872 if (cv != D_forecv)
873 continue;
874 KeypadMode(on);
878 void
879 LCursorkeysMode(l, on)
880 struct layer *l;
881 int on;
883 struct canvas *cv;
884 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
886 display = cv->c_display;
887 if (D_blocked)
888 continue;
889 if (cv != D_forecv)
890 continue;
891 CursorkeysMode(on);
895 void
896 LMouseMode(l, on)
897 struct layer *l;
898 int on;
900 struct canvas *cv;
901 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
903 display = cv->c_display;
904 if (D_blocked)
905 continue;
906 if (cv != D_forecv)
907 continue;
908 MouseMode(on);
912 void
913 LClearAll(l, uself)
914 struct layer *l;
915 int uself;
917 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
920 void
921 LRefreshAll(l, isblank)
922 struct layer *l;
923 int isblank;
925 struct layer *oldflayer;
926 int y;
928 debug1("LRefreshAll isblank=%d\n", isblank);
929 oldflayer = flayer;
930 flayer = l;
931 if (!isblank)
932 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0);
933 /* signal full refresh */
934 LayRedisplayLine(-1, -1, -1, 1);
935 for (y = 0; y < l->l_height; y++)
936 LayRedisplayLine(y, 0, l->l_width - 1, 1);
937 flayer = oldflayer;
940 void
941 /*VARARGS2*/
942 #if defined(USEVARARGS) && defined(__STDC__)
943 LMsg(int err, const char *fmt, VA_DOTS)
944 #else
945 LMsg(err, fmt, VA_DOTS)
946 int err;
947 const char *fmt;
948 VA_DECL
949 #endif
951 VA_LIST(ap)
952 char buf[MAXPATHLEN*2];
953 char *p = buf;
954 struct canvas *cv;
956 VA_START(ap, fmt);
957 fmt = DoNLS(fmt);
958 (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
959 VA_END(ap);
960 if (err)
962 p += strlen(p);
963 *p++ = ':';
964 *p++ = ' ';
965 strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
966 buf[sizeof(buf) - 1] = 0;
968 debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
969 for (display = displays; display; display = display->d_next)
971 for (cv = D_cvlist; cv; cv = cv->c_next)
972 if (cv->c_layer == flayer)
973 break;
974 if (cv == 0)
975 continue;
976 MakeStatus(buf);
981 /*******************************************************************/
982 /*******************************************************************/
985 * Layer creation / removal
988 void
989 KillLayerChain(lay)
990 struct layer *lay;
992 struct canvas *cv, *ncv;
993 struct layer *l, *oldflayer;
995 oldflayer = flayer;
996 debug1("KillLayerChain %#x\n", lay);
997 for (l = lay; l; l = l->l_next)
999 if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
1000 break;
1001 debug1("- killing %#x\n", l);
1002 if (oldflayer == l)
1003 oldflayer = 0;
1004 for (cv = l->l_cvlist; cv; cv = ncv)
1006 ncv = cv->c_lnext;
1007 cv->c_layer = 0;
1008 cv->c_lnext = 0;
1011 flayer = lay;
1012 while (flayer != l)
1013 ExitOverlayPage();
1014 flayer = oldflayer;
1020 InitOverlayPage(datasize, lf, block)
1021 int datasize;
1022 struct LayFuncs *lf;
1023 int block;
1025 char *data;
1026 struct layer *newlay;
1027 struct canvas *cv, *cvp, **cvpp;
1028 struct win *p;
1030 ASSERT(flayer);
1032 cv = 0;
1033 if (display && D_forecv->c_layer == flayer)
1034 cv = D_forecv; /* work only on this cv! */
1036 if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0)
1038 Msg(0, "No memory for layer struct");
1039 return -1;
1041 debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
1042 data = 0;
1043 if (datasize)
1045 if ((data = calloc(1, datasize)) == 0)
1047 free((char *)newlay);
1048 Msg(0, "No memory for layer data");
1049 return -1;
1053 p = Layer2Window(flayer);
1055 if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0)))
1057 if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0)
1058 KillLayerChain(p->w_savelayer);
1059 p->w_savelayer = newlay;
1062 if (cv && flayer->l_next == 0 && !block)
1064 struct display *olddisplay = display;
1065 display = cv->c_display;
1066 RemoveStatus();
1067 display = olddisplay;
1069 /* new branch -> just get canvas vps */
1070 for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
1071 if (cvp == cv)
1072 break;
1073 ASSERT(cvp);
1074 *cvpp = cv->c_lnext;
1075 newlay->l_cvlist = cv;
1076 cv->c_lnext = 0;
1077 cv->c_layer = newlay;
1079 else
1081 LAY_DISPLAYS(flayer, RemoveStatus());
1082 if (block)
1083 debug("layer is blocking\n");
1084 if (block && flayer->l_layfn == &WinLf)
1086 debug("...and is first, so window gets blocked\n");
1087 ASSERT(p->w_blocked == 0);
1088 p->w_blocked++;
1089 newlay->l_blocking = 1;
1091 /* change all canvases */
1092 newlay->l_cvlist = flayer->l_cvlist;
1093 for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
1094 cvp->c_layer = newlay;
1095 flayer->l_cvlist = 0;
1097 newlay->l_width = flayer->l_width;
1098 newlay->l_height = flayer->l_height;
1099 newlay->l_encoding = 0;
1100 newlay->l_layfn = lf;
1101 newlay->l_data = data;
1102 newlay->l_next = flayer;
1103 newlay->l_bottom = flayer->l_bottom;
1104 flayer = newlay;
1105 LayRestore();
1106 return 0;
1109 extern struct layout *layouts;
1111 void
1112 ExitOverlayPage()
1114 struct layer *oldlay;
1115 struct win *p;
1116 int doredisplay = 0;
1117 struct canvas *cv, *ocv;
1118 struct layout *lay;
1120 ASSERT(flayer);
1121 debug1("Exiting layer %#x\n", (unsigned int)flayer);
1122 oldlay = flayer;
1123 if (oldlay->l_data)
1125 if (oldlay->l_layfn->lf_LayFree)
1126 LayFree(oldlay->l_data);
1127 free(oldlay->l_data);
1130 p = Layer2Window(flayer);
1132 flayer = oldlay->l_next;
1133 if (flayer->l_layfn == &WinLf)
1135 if (oldlay->l_blocking)
1137 ASSERT(p->w_blocked > 0);
1138 p->w_blocked--;
1139 debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked);
1141 /* don't warp dead layers: check cvlist */
1142 if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist)
1144 debug("warping to top of blocking chain!\n");
1145 /* warp ourself into savelayer */
1146 flayer = p->w_savelayer;
1147 doredisplay = 1;
1150 if (p && p->w_savelayer == oldlay)
1151 p->w_savelayer = flayer;
1152 #ifdef COPY_PASTE
1153 if (p && oldlay == p->w_paster.pa_pastelayer)
1154 p->w_paster.pa_pastelayer = 0;
1155 #endif
1157 for (lay = layouts; lay; lay = lay->lay_next)
1158 for (cv = lay->lay_cvlist; cv; cv = cv->c_next)
1159 if (cv->c_layer == oldlay)
1160 cv->c_layer = flayer;
1162 /* add all canvases back into next layer's canvas list */
1163 for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext)
1165 cv->c_layer = flayer;
1166 ocv = cv;
1168 if (ocv)
1170 cv = flayer->l_cvlist;
1171 ocv->c_lnext = 0;
1172 flayer->l_cvlist = oldlay->l_cvlist;
1173 /* redisplay only the warped cvs */
1174 if (doredisplay)
1175 LRefreshAll(flayer, 0);
1176 ocv->c_lnext = cv;
1178 oldlay->l_cvlist = 0;
1179 LayerCleanupMemory(oldlay);
1180 free((char *)oldlay);
1181 LayRestore();
1182 LaySetCursor();
1186 LayProcessMouse(struct layer *l, unsigned char ch)
1188 /* XXX: Make sure the layer accepts mouse events */
1189 int len;
1191 if (l->l_mouseevent.len >= sizeof(l->l_mouseevent.buffer))
1192 return -1;
1194 len = l->l_mouseevent.len++;
1195 l->l_mouseevent.buffer[len] = (len > 0 ? ch - 33 : ch);
1196 return (l->l_mouseevent.len == sizeof(l->l_mouseevent.buffer));
1200 LayProcessMouseSwitch(struct layer *l, int s)
1202 if ((l->l_mouseevent.start = s))
1204 l->l_mouseevent.len = 0;
1208 void LayPause(layer, pause)
1209 struct layer *layer;
1210 int pause;
1212 struct canvas *cv;
1213 struct display *olddisplay = display;
1214 int line;
1216 pause = !!pause;
1218 if (layer->l_pause.d == pause)
1219 return;
1221 if ((layer->l_pause.d = pause))
1223 /* Start pausing */
1224 layer->l_pause.top = layer->l_pause.bottom = -1;
1225 return;
1228 /* Unpause. So refresh the regions in the displays! */
1229 if (layer->l_pause.top == -1 &&
1230 layer->l_pause.bottom == -1)
1231 return;
1233 for (cv = layer->l_cvlist; cv; cv = cv->c_lnext)
1235 struct viewport *vp;
1237 display = cv->c_display;
1239 for (vp = cv->c_vplist; vp; vp = vp->v_next)
1241 for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
1243 int xs, xe;
1245 if (line + vp->v_yoff >= vp->v_ys && line + vp->v_yoff <= vp->v_ye &&
1246 ((xs = layer->l_pause.left[line]) >= 0) &&
1247 ((xe = layer->l_pause.right[line]) >= 0))
1249 xs += vp->v_xoff;
1250 xe += vp->v_xoff;
1252 if (xs < vp->v_xs) xs = vp->v_xs;
1253 if (xe > vp->v_xe) xe = vp->v_xe;
1255 if (xs <= xe)
1256 RefreshLine(line + vp->v_yoff, xs, xe, 0);
1261 if (cv == D_forecv)
1263 int cx = layer->l_x + cv->c_xoff;
1264 int cy = layer->l_y + cv->c_yoff;
1266 if (cx < cv->c_xs) cx = cv->c_xs;
1267 if (cy < cv->c_ys) cy = cv->c_ys;
1268 if (cx > cv->c_xe) cx = cv->c_xe;
1269 if (cy > cv->c_ye) cy = cv->c_ye;
1271 GotoPos(cx, cy);
1275 for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
1276 layer->l_pause.left[line] = layer->l_pause.right[line] = -1;
1277 olddisplay = display;
1280 void
1281 LayPauseUpdateRegion(layer, xs, xe, ys, ye)
1282 struct layer *layer;
1283 int xs, xe;
1284 int ys, ye;
1286 if (!layer->l_pause.d)
1287 return;
1288 if (ys < 0)
1289 ys = 0;
1290 if (ye >= layer->l_height)
1291 ye = layer->l_height - 1;
1292 if (xe >= layer->l_width)
1293 xe = layer->l_width - 1;
1295 if (layer->l_pause.top == -1 || layer->l_pause.top > ys)
1296 layer->l_pause.top = ys;
1297 if (layer->l_pause.bottom < ye)
1299 layer->l_pause.bottom = ye;
1300 if (layer->l_pause.lines <= ye)
1302 int o = layer->l_pause.lines;
1303 layer->l_pause.lines = ye + 32;
1304 layer->l_pause.left = realloc(layer->l_pause.left, sizeof(int) * layer->l_pause.lines);
1305 layer->l_pause.right = realloc(layer->l_pause.right, sizeof(int) * layer->l_pause.lines);
1306 while (o < layer->l_pause.lines)
1308 layer->l_pause.left[o] = layer->l_pause.right[o] = -1;
1309 o++;
1314 while (ys <= ye)
1316 if (layer->l_pause.left[ys] == -1 || layer->l_pause.left[ys] > xs)
1317 layer->l_pause.left[ys] = xs;
1318 if (layer->l_pause.right[ys] < xe)
1319 layer->l_pause.right[ys] = xe;
1320 ys++;
1324 void
1325 LayerCleanupMemory(layer)
1326 struct layer *layer;
1328 if (layer->l_pause.left)
1329 free(layer->l_pause.left);
1330 if (layer->l_pause.right)
1331 free(layer->l_pause.right);