Bring back --with-sys-screenrc configure flag.
[screen-lua.git] / src / layer.c
blobaeea318d05ef95ef81fe15aa372c63d53f46db91
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
89 #define FOR_EACH_UNPAUSED_CANVAS(l, fn) for (cv = (l)->l_cvlist; cv; cv = cv->c_lnext) \
90 { \
91 if ((l)->l_pause.d && cv->c_slorient) \
92 continue; \
93 fn \
96 void
97 LGotoPos(l, x, y)
98 struct layer *l;
99 int x, y;
101 struct canvas *cv;
102 struct viewport *vp;
103 int x2, y2;
105 if (l->l_pause.d)
106 LayPauseUpdateRegion(l, x, x, y, y);
108 #ifdef HAVE_BRAILLE
109 if (bd.bd_refreshing)
110 return;
111 #endif
112 FOR_EACH_UNPAUSED_CANVAS(l,
114 display = cv->c_display;
115 if (D_blocked)
116 continue;
117 if (cv != D_forecv)
118 continue;
119 x2 = x + cv->c_xoff;
120 y2 = y + cv->c_yoff;
121 debug2("---LGotoPos %d %d\n", x2, y2);
122 if (x2 < cv->c_xs)
123 x2 = cv->c_xs;
124 if (y2 < cv->c_ys)
125 y2 = cv->c_ys;
126 if (x2 > cv->c_xe)
127 x2 = cv->c_xe;
128 if (y2 > cv->c_ye)
129 y2 = cv->c_ye;
130 for (vp = cv->c_vplist; vp; vp = vp->v_next)
132 if (x2 < vp->v_xs || x2 > vp->v_xe)
133 continue;
134 if (y2 < vp->v_ys || y2 > vp->v_ye)
135 continue;
136 GotoPos(x2, y2);
137 break;
143 void
144 LScrollH(l, n, y, xs, xe, bce, ol)
145 struct layer *l;
146 int n, y, xs, xe;
147 int bce;
148 struct mline *ol;
150 struct canvas *cv;
151 struct viewport *vp;
152 int y2, xs2, xe2;
154 if (n == 0)
155 return;
156 if (l->l_pause.d)
157 LayPauseUpdateRegion(l, xs, xe, y, y);
158 FOR_EACH_UNPAUSED_CANVAS(l,
159 for (vp = cv->c_vplist; vp; vp = vp->v_next)
161 y2 = y + vp->v_yoff;
162 if (y2 < vp->v_ys || y2 > vp->v_ye)
163 continue;
164 xs2 = xs + vp->v_xoff;
165 xe2 = xe + vp->v_xoff;
166 if (xs2 < vp->v_xs)
167 xs2 = vp->v_xs;
168 if (xe2 > vp->v_xe)
169 xe2 = vp->v_xe;
170 if (xs2 > xe2)
171 continue;
172 display = cv->c_display;
173 if (D_blocked)
174 continue;
175 ScrollH(y2, xs2, xe2, n, bce, ol ? mloff(ol, -vp->v_xoff) : 0);
176 if (xe2 - xs2 == xe - xs)
177 continue;
178 if (n > 0)
180 xs2 = xe2 + 1 - n;
181 xe2 = xe + vp->v_xoff - n;
183 else
185 xe2 = xs2 - 1 - n;
186 xs2 = xs + vp->v_xoff - n;
188 if (xs2 < vp->v_xs)
189 xs2 = vp->v_xs;
190 if (xe2 > vp->v_xe)
191 xe2 = vp->v_xe;
192 if (xs2 <= xe2)
193 RefreshArea(xs2, y2, xe2, y2, 1);
198 void
199 LScrollV(l, n, ys, ye, bce)
200 struct layer *l;
201 int n;
202 int ys, ye;
203 int bce;
205 struct canvas *cv;
206 struct viewport *vp;
207 int ys2, ye2, xs2, xe2;
208 if (n == 0)
209 return;
210 if (l->l_pause.d)
211 LayPauseUpdateRegion(l, 0, l->l_width - 1, ys, ye);
212 FOR_EACH_UNPAUSED_CANVAS(l,
213 for (vp = cv->c_vplist; vp; vp = vp->v_next)
215 xs2 = vp->v_xoff;
216 xe2 = l->l_width - 1 + vp->v_xoff;
217 ys2 = ys + vp->v_yoff;
218 ye2 = ye + vp->v_yoff;
219 if (xs2 < vp->v_xs)
220 xs2 = vp->v_xs;
221 if (xe2 > vp->v_xe)
222 xe2 = vp->v_xe;
223 if (ys2 < vp->v_ys)
224 ys2 = vp->v_ys;
225 if (ye2 > vp->v_ye)
226 ye2 = vp->v_ye;
227 if (ys2 > ye2 || xs2 > xe2)
228 continue;
229 display = cv->c_display;
230 if (D_blocked)
231 continue;
232 #if 0
233 ScrollV(xs2, ys2, xe2, ye2, n, bce);
234 #else
235 ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n, bce);
236 #endif
237 debug2("LScrollV: %d %d", ys, ye);
238 debug2(" -> %d %d\n", ys2, ye2);
239 if (ye2 - ys2 == ye - ys)
240 continue;
241 if (n > 0)
243 ys2 = ye2 + 1 - n;
244 ye2 = ye + vp->v_yoff - n;
246 else
248 ye2 = ys2 - 1 - n;
249 ys2 = ys + vp->v_yoff - n;
251 debug2("LScrollV: - %d %d\n", ys2, ye2);
252 if (ys2 < vp->v_ys)
253 ys2 = vp->v_ys;
254 if (ye2 > vp->v_ye)
255 ye2 = vp->v_ye;
256 debug2("LScrollV: - %d %d\n", ys2, ye2);
257 if (ys2 <= ye2)
258 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)
277 LayPauseUpdateRegion(l, x, l->l_width - 1, y, y);
278 FOR_EACH_UNPAUSED_CANVAS(l,
279 for (vp = cv->c_vplist; vp; vp = vp->v_next)
281 y2 = y + vp->v_yoff;
282 if (y2 < vp->v_ys || y2 > vp->v_ye)
283 continue;
284 xs2 = x + vp->v_xoff;
285 xe2 = l->l_width - 1 + vp->v_xoff;
286 c2 = c;
287 f = 0;
288 if (xs2 < vp->v_xs)
290 xs2 = vp->v_xs;
291 c2 = &mchar_blank;
292 if (ol)
294 int i;
295 i = xs2 - vp->v_xoff - 1;
296 if (i >= 0 && i < l->l_width)
298 copy_mline2mchar(&cc, ol, i);
299 c2 = &cc;
302 else
303 f = 1;
305 if (xe2 > vp->v_xe)
306 xe2 = vp->v_xe;
307 if (xs2 > xe2)
308 continue;
309 display = cv->c_display;
310 if (D_blocked)
311 continue;
312 rol = RECODE_MLINE(ol);
313 InsChar(RECODE_MCHAR(c2), xs2, xe2, y2, mloff(rol, -vp->v_xoff));
314 if (f)
315 RefreshArea(xs2, y2, xs2, y2, 1);
320 void
321 LPutChar(l, c, x, y)
322 struct layer *l;
323 struct mchar *c;
324 int x, y;
326 struct canvas *cv;
327 struct viewport *vp;
328 int x2, y2;
329 #ifdef HAVE_BRAILLE
330 if (bd.bd_refreshing)
332 BPutChar(l, c, x, y);
333 return;
335 #endif
337 if (l->l_pause.d)
338 LayPauseUpdateRegion(l, x,
339 #ifdef DW_CHARS
340 x + (c->mbcs ? 1 : 0)
341 #else
343 #endif
344 , y, y);
346 FOR_EACH_UNPAUSED_CANVAS(l,
348 display = cv->c_display;
349 if (D_blocked)
350 continue;
351 for (vp = cv->c_vplist; vp; vp = vp->v_next)
353 y2 = y + vp->v_yoff;
354 if (y2 < vp->v_ys || y2 > vp->v_ye)
355 continue;
356 x2 = x + vp->v_xoff;
357 if (x2 < vp->v_xs || x2 > vp->v_xe)
358 continue;
359 PutChar(RECODE_MCHAR(c), x2, y2);
360 break;
366 void
367 LPutStr(l, s, n, r, x, y)
368 struct layer *l;
369 char *s;
370 int n;
371 struct mchar *r;
372 int x, y;
374 struct canvas *cv;
375 struct viewport *vp;
376 char *s2;
377 int xs2, xe2, y2;
379 if (x + n > l->l_width)
380 n = l->l_width - x;
381 #ifdef HAVE_BRAILLE
382 if (bd.bd_refreshing)
384 BPutStr(l, s, n, r, x, y);
385 return;
387 #endif
388 if (l->l_pause.d)
389 LayPauseUpdateRegion(l, x, x + n - 1, y, y);
391 FOR_EACH_UNPAUSED_CANVAS(l,
392 for (vp = cv->c_vplist; vp; vp = vp->v_next)
394 y2 = y + vp->v_yoff;
395 if (y2 < vp->v_ys || y2 > vp->v_ye)
396 continue;
397 xs2 = x + vp->v_xoff;
398 xe2 = xs2 + n - 1;
399 if (xs2 < vp->v_xs)
400 xs2 = vp->v_xs;
401 if (xe2 > vp->v_xe)
402 xe2 = vp->v_xe;
403 if (xs2 > xe2)
404 continue;
405 display = cv->c_display;
406 if (D_blocked)
407 continue;
408 GotoPos(xs2, y2);
409 SetRendition(r);
410 s2 = s + xs2 - x - vp->v_xoff;
411 #ifdef UTF8
412 if (D_encoding == UTF8 && l->l_encoding != UTF8 && (r->font || l->l_encoding))
414 struct mchar mc;
415 mc = *r;
416 while (xs2 <= xe2)
418 mc.image = *s2++;
419 PutChar(RECODE_MCHAR(&mc), xs2++, y2);
421 continue;
423 #endif
424 while (xs2++ <= xe2)
425 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)
453 LayPauseUpdateRegion(l, x, x + n - 1, y, y);
454 len = strlen(s);
455 if (len > n)
456 len = n;
457 FOR_EACH_UNPAUSED_CANVAS(l,
458 for (vp = cv->c_vplist; vp; vp = vp->v_next)
460 y2 = y + vp->v_yoff;
461 if (y2 < vp->v_ys || y2 > vp->v_ye)
462 continue;
463 xs2 = x + vp->v_xoff;
464 xe2 = xs2 + n - 1;
465 if (xs2 < vp->v_xs)
466 xs2 = vp->v_xs;
467 if (xe2 > vp->v_xe)
468 xe2 = vp->v_xe;
469 if (xs2 > xe2)
470 continue;
471 display = cv->c_display;
472 if (D_blocked)
473 continue;
474 GotoPos(xs2, y2);
475 SetRendition(r);
476 len2 = xe2 - (x + vp->v_xoff) + 1;
477 if (len2 > len)
478 len2 = len;
479 PutWinMsg(s, xs2 - x - vp->v_xoff, len2);
480 xs2 = x + vp->v_xoff + len2;
481 if (xs2 < vp->v_xs)
482 xs2 = vp->v_xs;
483 or = D_rend;
484 GotoPos(xs2, y2);
485 SetRendition(&or);
486 while (xs2++ <= xe2)
487 PUTCHARLP(' ');
492 void
493 LClearLine(l, y, xs, xe, bce, ol)
494 struct layer *l;
495 int xs, xe, bce;
496 struct mline *ol;
498 struct canvas *cv;
499 struct viewport *vp;
500 int y2, xs2, xe2;
502 /* check for magic margin condition */
503 if (xs >= l->l_width)
504 xs = l->l_width - 1;
505 if (xe >= l->l_width)
506 xe = l->l_width - 1;
507 if (l->l_pause.d)
508 LayPauseUpdateRegion(l, xs, xe, y, y);
509 FOR_EACH_UNPAUSED_CANVAS(l,
510 for (vp = cv->c_vplist; vp; vp = vp->v_next)
512 xs2 = xs + vp->v_xoff;
513 xe2 = xe + vp->v_xoff;
514 y2 = y + vp->v_yoff;
515 if (y2 < vp->v_ys || y2 > vp->v_ye)
516 continue;
517 if (xs2 < vp->v_xs)
518 xs2 = vp->v_xs;
519 if (xe2 > vp->v_xe)
520 xe2 = vp->v_xe;
521 if (xs2 > xe2)
522 continue;
523 display = cv->c_display;
524 if (D_blocked)
525 continue;
526 ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
531 void
532 LClearArea(l, xs, ys, xe, ye, bce, uself)
533 struct layer *l;
534 int xs, ys, xe, ye;
535 int bce;
536 int uself;
538 struct canvas *cv;
539 struct viewport *vp;
540 int xs2, ys2, xe2, ye2;
541 #ifdef HAVE_BRAILLE
542 if (bd.bd_refreshing)
543 return;
544 #endif
545 /* Check for zero-height window */
546 if (ys < 0 || ye < ys)
547 return;
549 /* check for magic margin condition */
550 if (xs >= l->l_width)
551 xs = l->l_width - 1;
552 if (xe >= l->l_width)
553 xe = l->l_width - 1;
554 if (l->l_pause.d)
555 LayPauseUpdateRegion(l, xs, xe, ys, ye);
556 FOR_EACH_UNPAUSED_CANVAS(l,
558 display = cv->c_display;
559 if (D_blocked)
560 continue;
561 for (vp = cv->c_vplist; vp; vp = vp->v_next)
563 xs2 = xs + vp->v_xoff;
564 xe2 = xe + vp->v_xoff;
565 ys2 = ys + vp->v_yoff;
566 ye2 = ye + vp->v_yoff;
567 if (xs2 < vp->v_xs)
568 xs2 = vp->v_xs;
569 if (xe2 > vp->v_xe)
570 xe2 = vp->v_xe;
571 if (xs2 > vp->v_xe)
572 ys2++;
573 if (xe2 < vp->v_xs)
574 ye2--;
575 if (ys2 < vp->v_ys)
576 ys2 = vp->v_ys;
577 if (ye2 > vp->v_ye)
578 ye2 = vp->v_ye;
579 if (ys2 > ye2)
580 continue;
581 #if 0
582 xcs = vp->v_xoff;
583 xce = l->l_width - 1 + vp->v_xoff;
584 if (xcs < vp->v_xs)
585 xcs = vp->v_xs;
586 if (xce > vp->v_xe)
587 xce = vp->v_xe;
588 if (xcs > xce)
589 continue;
590 if (ys2 != ys + vp->v_yoff)
591 xs2 = xcs;
592 if (ye2 != ye + vp->v_yoff)
593 xe2 = xce;
594 display = cv->c_display;
595 ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself);
596 #else
597 if (xs == 0 || ys2 != ys + vp->v_yoff)
598 xs2 = vp->v_xs;
599 if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
600 xe2 = vp->v_xe;
601 display = cv->c_display;
602 ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself);
603 if (xe == l->l_width - 1 && xe2 > vp->v_xoff + xe)
605 int y;
606 SetRendition(&mchar_blank);
607 for (y = ys2; y <= ye2; y++)
609 GotoPos(xe + vp->v_xoff + 1, y);
610 PUTCHARLP('|');
613 #endif
619 void
620 LCDisplayLine(l, ml, y, xs, xe, isblank)
621 struct layer *l;
622 struct mline *ml;
623 int y, xs, xe;
624 int isblank;
626 struct canvas *cv;
627 struct viewport *vp;
628 int xs2, xe2, y2;
629 #ifdef HAVE_BRAILLE
630 if (bd.bd_refreshing)
632 BCDisplayLine(l, ml, y, xs, xe, isblank);
633 return;
635 #endif
636 if (l->l_pause.d)
637 LayPauseUpdateRegion(l, xs, xe, y, y);
638 FOR_EACH_UNPAUSED_CANVAS(l,
640 display = cv->c_display;
641 if (D_blocked)
642 continue;
643 for (vp = cv->c_vplist; vp; vp = vp->v_next)
645 xs2 = xs + vp->v_xoff;
646 xe2 = xe + vp->v_xoff;
647 y2 = y + vp->v_yoff;
648 if (y2 < vp->v_ys || y2 > vp->v_ye)
649 continue;
650 if (xs2 < vp->v_xs)
651 xs2 = vp->v_xs;
652 if (xe2 > vp->v_xe)
653 xe2 = vp->v_xe;
654 if (xs2 > xe2)
655 continue;
656 display = cv->c_display;
657 debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
658 debug1(" mloff = %d\n", -vp->v_xoff);
659 DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
665 void
666 LCDisplayLineWrap(l, ml, y, from, to, isblank)
667 struct layer *l;
668 struct mline *ml;
669 int y, from, to;
670 int isblank;
672 struct mchar nc;
673 copy_mline2mchar(&nc, ml, 0);
674 #ifdef DW_CHARS
675 if (dw_left(ml, 0, l->l_encoding))
677 nc.mbcs = ml->image[1];
678 from++;
680 #endif
681 LWrapChar(l, &nc, y - 1, -1, -1, 0);
682 from++;
683 if (from <= to)
684 LCDisplayLine(l, ml, y, from, to, isblank);
687 void
688 LSetRendition(l, r)
689 struct layer *l;
690 struct mchar *r;
692 struct canvas *cv;
694 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
696 display = cv->c_display;
697 if (D_blocked)
698 continue;
699 SetRendition(r);
703 void
704 LWrapChar(l, c, y, top, bot, ins)
705 struct layer *l;
706 struct mchar *c;
707 int y, top, bot;
708 int ins;
710 struct canvas *cv, *cvlist, *cvlnext;
711 struct viewport *vp, *evp, **vpp;
712 int yy, y2, yy2, top2, bot2;
713 int bce;
715 if (l->l_pause.d)
716 /* XXX: 'y'? */
717 LayPauseUpdateRegion(l, 0, l->l_width - 1, top, bot);
719 #ifdef COLOR
720 bce = rend_getbg(c);
721 #else
722 bce = 0;
723 #endif
724 if (y != bot)
726 /* simple case: no scrolling */
728 /* cursor after wrapping */
729 yy = y == l->l_height - 1 ? y : y + 1;
731 FOR_EACH_UNPAUSED_CANVAS(l,
733 y2 = 0; /* gcc -Wall */
734 display = cv->c_display;
735 if (D_blocked)
736 continue;
737 /* find the viewport of the wrapped character */
738 for (vp = cv->c_vplist; vp; vp = vp->v_next)
740 y2 = y + vp->v_yoff;
741 yy2 = yy + vp->v_yoff;
742 if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
743 break;
745 if (vp == 0)
746 continue; /* nothing to do, character not visible */
747 /* find the viewport of the character at the end of the line*/
748 for (evp = cv->c_vplist; evp; evp = evp->v_next)
749 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)
750 break; /* gotcha! */
751 if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye))
753 /* no wrapping possible */
754 debug("LWrap: can't wrap!\n");
755 cvlist = l->l_cvlist;
756 cvlnext = cv->c_lnext;
757 l->l_cvlist = cv;
758 cv->c_lnext = 0;
759 if (ins)
760 LInsChar(l, c, 0, yy, 0);
761 else
762 LPutChar(l, c, 0, yy);
763 l->l_cvlist = cvlist;
764 cv->c_lnext = cvlnext;
766 else
768 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_EACH_UNPAUSED_CANVAS(l,
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);
830 void
831 LCursorVisibility(l, vis)
832 struct layer *l;
833 int vis;
835 struct canvas *cv;
836 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
838 display = cv->c_display;
839 if (D_blocked)
840 continue;
841 if (cv != D_forecv)
842 continue;
843 CursorVisibility(vis);
847 void
848 LSetFlow(l, flow)
849 struct layer *l;
850 int flow;
852 struct canvas *cv;
853 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
855 display = cv->c_display;
856 if (cv != D_forecv)
857 continue;
858 SetFlow(flow);
862 void
863 LKeypadMode(l, on)
864 struct layer *l;
865 int on;
867 struct canvas *cv;
868 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
870 display = cv->c_display;
871 if (D_blocked)
872 continue;
873 if (cv != D_forecv)
874 continue;
875 KeypadMode(on);
879 void
880 LCursorkeysMode(l, on)
881 struct layer *l;
882 int on;
884 struct canvas *cv;
885 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
887 display = cv->c_display;
888 if (D_blocked)
889 continue;
890 if (cv != D_forecv)
891 continue;
892 CursorkeysMode(on);
896 void
897 LMouseMode(l, on)
898 struct layer *l;
899 int on;
901 struct canvas *cv;
902 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
904 display = cv->c_display;
905 if (D_blocked)
906 continue;
907 if (cv != D_forecv)
908 continue;
909 MouseMode(on);
913 void
914 LClearAll(l, uself)
915 struct layer *l;
916 int uself;
918 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
921 void
922 LRefreshAll(l, isblank)
923 struct layer *l;
924 int isblank;
926 struct layer *oldflayer;
927 int y;
929 debug1("LRefreshAll isblank=%d\n", isblank);
930 oldflayer = flayer;
931 flayer = l;
932 if (!isblank)
933 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0);
934 /* signal full refresh */
935 LayRedisplayLine(-1, -1, -1, 1);
936 for (y = 0; y < l->l_height; y++)
937 LayRedisplayLine(y, 0, l->l_width - 1, 1);
938 flayer = oldflayer;
941 void
942 /*VARARGS2*/
943 #if defined(USEVARARGS) && defined(__STDC__)
944 LMsg(int err, const char *fmt, VA_DOTS)
945 #else
946 LMsg(err, fmt, VA_DOTS)
947 int err;
948 const char *fmt;
949 VA_DECL
950 #endif
952 VA_LIST(ap)
953 char buf[MAXPATHLEN*2];
954 char *p = buf;
955 struct canvas *cv;
957 VA_START(ap, fmt);
958 fmt = DoNLS(fmt);
959 (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
960 VA_END(ap);
961 if (err)
963 p += strlen(p);
964 *p++ = ':';
965 *p++ = ' ';
966 strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
967 buf[sizeof(buf) - 1] = 0;
969 debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
970 for (display = displays; display; display = display->d_next)
972 for (cv = D_cvlist; cv; cv = cv->c_next)
973 if (cv->c_layer == flayer)
974 break;
975 if (cv == 0)
976 continue;
977 MakeStatus(buf);
982 /*******************************************************************/
983 /*******************************************************************/
986 * Layer creation / removal
989 void
990 KillLayerChain(lay)
991 struct layer *lay;
993 struct canvas *cv, *ncv;
994 struct layer *l, *oldflayer;
996 oldflayer = flayer;
997 debug1("KillLayerChain %#x\n", lay);
998 for (l = lay; l; l = l->l_next)
1000 if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
1001 break;
1002 debug1("- killing %#x\n", l);
1003 if (oldflayer == l)
1004 oldflayer = 0;
1005 for (cv = l->l_cvlist; cv; cv = ncv)
1007 ncv = cv->c_lnext;
1008 cv->c_layer = 0;
1009 cv->c_lnext = 0;
1012 flayer = lay;
1013 while (flayer != l)
1014 ExitOverlayPage();
1015 flayer = oldflayer;
1021 InitOverlayPage(datasize, lf, block)
1022 int datasize;
1023 struct LayFuncs *lf;
1024 int block;
1026 char *data;
1027 struct layer *newlay;
1028 struct canvas *cv, *cvp, **cvpp;
1029 struct win *p;
1031 ASSERT(flayer);
1033 cv = 0;
1034 if (display && D_forecv->c_layer == flayer)
1035 cv = D_forecv; /* work only on this cv! */
1037 if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0)
1039 Msg(0, "No memory for layer struct");
1040 return -1;
1042 debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
1043 data = 0;
1044 if (datasize)
1046 if ((data = calloc(1, datasize)) == 0)
1048 free((char *)newlay);
1049 Msg(0, "No memory for layer data");
1050 return -1;
1054 p = Layer2Window(flayer);
1056 if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0)))
1058 if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0)
1059 KillLayerChain(p->w_savelayer);
1060 p->w_savelayer = newlay;
1063 if (cv && flayer->l_next == 0 && !block)
1065 struct display *olddisplay = display;
1066 display = cv->c_display;
1067 RemoveStatus();
1068 display = olddisplay;
1070 /* new branch -> just get canvas vps */
1071 for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
1072 if (cvp == cv)
1073 break;
1074 ASSERT(cvp);
1075 *cvpp = cv->c_lnext;
1076 newlay->l_cvlist = cv;
1077 cv->c_lnext = 0;
1078 cv->c_layer = newlay;
1080 else
1082 LAY_DISPLAYS(flayer, RemoveStatus());
1083 if (block)
1084 debug("layer is blocking\n");
1085 if (block && flayer->l_layfn == &WinLf)
1087 debug("...and is first, so window gets blocked\n");
1088 ASSERT(p->w_blocked == 0);
1089 p->w_blocked++;
1090 newlay->l_blocking = 1;
1092 /* change all canvases */
1093 newlay->l_cvlist = flayer->l_cvlist;
1094 for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
1095 cvp->c_layer = newlay;
1096 flayer->l_cvlist = 0;
1098 newlay->l_width = flayer->l_width;
1099 newlay->l_height = flayer->l_height;
1100 newlay->l_encoding = 0;
1101 newlay->l_layfn = lf;
1102 newlay->l_data = data;
1103 newlay->l_next = flayer;
1104 newlay->l_bottom = flayer->l_bottom;
1105 flayer = newlay;
1106 LayRestore();
1107 return 0;
1110 extern struct layout *layouts;
1112 void
1113 ExitOverlayPage()
1115 struct layer *oldlay;
1116 struct win *p;
1117 int doredisplay = 0;
1118 struct canvas *cv, *ocv;
1119 struct layout *lay;
1121 ASSERT(flayer);
1122 debug1("Exiting layer %#x\n", (unsigned int)flayer);
1123 oldlay = flayer;
1124 if (oldlay->l_data)
1126 if (oldlay->l_layfn->lf_LayFree)
1127 LayFree(oldlay->l_data);
1128 free(oldlay->l_data);
1131 p = Layer2Window(flayer);
1133 flayer = oldlay->l_next;
1134 if (flayer->l_layfn == &WinLf)
1136 if (oldlay->l_blocking)
1138 ASSERT(p->w_blocked > 0);
1139 p->w_blocked--;
1140 debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked);
1142 /* don't warp dead layers: check cvlist */
1143 if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist)
1145 debug("warping to top of blocking chain!\n");
1146 /* warp ourself into savelayer */
1147 flayer = p->w_savelayer;
1148 doredisplay = 1;
1151 if (p && p->w_savelayer == oldlay)
1152 p->w_savelayer = flayer;
1153 #ifdef COPY_PASTE
1154 if (p && oldlay == p->w_paster.pa_pastelayer)
1155 p->w_paster.pa_pastelayer = 0;
1156 #endif
1158 for (lay = layouts; lay; lay = lay->lay_next)
1159 for (cv = lay->lay_cvlist; cv; cv = cv->c_next)
1160 if (cv->c_layer == oldlay)
1161 cv->c_layer = flayer;
1163 /* add all canvases back into next layer's canvas list */
1164 for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext)
1166 cv->c_layer = flayer;
1167 ocv = cv;
1169 if (ocv)
1171 cv = flayer->l_cvlist;
1172 ocv->c_lnext = 0;
1173 flayer->l_cvlist = oldlay->l_cvlist;
1174 /* redisplay only the warped cvs */
1175 if (doredisplay)
1176 LRefreshAll(flayer, 0);
1177 ocv->c_lnext = cv;
1179 oldlay->l_cvlist = 0;
1180 LayerCleanupMemory(oldlay);
1181 free((char *)oldlay);
1182 LayRestore();
1183 LaySetCursor();
1187 LayProcessMouse(struct layer *l, unsigned char ch)
1189 /* XXX: Make sure the layer accepts mouse events */
1190 int len;
1192 if (l->l_mouseevent.len >= sizeof(l->l_mouseevent.buffer))
1193 return -1;
1195 len = l->l_mouseevent.len++;
1196 l->l_mouseevent.buffer[len] = (len > 0 ? ch - 33 : ch);
1197 return (l->l_mouseevent.len == sizeof(l->l_mouseevent.buffer));
1201 LayProcessMouseSwitch(struct layer *l, int s)
1203 if ((l->l_mouseevent.start = s))
1205 l->l_mouseevent.len = 0;
1209 void LayPause(layer, pause)
1210 struct layer *layer;
1211 int pause;
1213 struct canvas *cv;
1214 struct display *olddisplay = display;
1215 int line;
1216 struct win *win;
1218 pause = !!pause;
1220 if (layer->l_pause.d == pause)
1221 return;
1223 if ((layer->l_pause.d = pause))
1225 /* Start pausing */
1226 layer->l_pause.top = layer->l_pause.bottom = -1;
1227 return;
1230 /* Unpause. So refresh the regions in the displays! */
1231 if (layer->l_pause.top == -1 &&
1232 layer->l_pause.bottom == -1)
1233 return;
1235 if (layer->l_layfn == &WinLf) /* Currently, this will always be the case! */
1236 win = layer->l_data;
1237 else
1238 win = NULL;
1240 for (cv = layer->l_cvlist; cv; cv = cv->c_lnext)
1242 struct viewport *vp;
1244 if (!cv->c_slorient)
1245 continue; /* Wasn't split, so already updated. */
1247 display = cv->c_display;
1249 for (vp = cv->c_vplist; vp; vp = vp->v_next)
1251 for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
1253 int xs, xe;
1255 if (line + vp->v_yoff >= vp->v_ys && line + vp->v_yoff <= vp->v_ye &&
1256 ((xs = layer->l_pause.left[line]) >= 0) &&
1257 ((xe = layer->l_pause.right[line]) >= 0))
1259 xs += vp->v_xoff;
1260 xe += vp->v_xoff;
1262 if (xs < vp->v_xs) xs = vp->v_xs;
1263 if (xe > vp->v_xe) xe = vp->v_xe;
1265 #if defined(DW_CHARS) && defined(UTF8)
1266 if (layer->l_encoding == UTF8 && xe < vp->v_xe && win)
1268 struct mline *ml = win->w_mlines + line;
1269 if (dw_left(ml, xe, UTF8))
1270 xe++;
1272 #endif
1274 if (xs <= xe)
1275 RefreshLine(line + vp->v_yoff, xs, xe, 0);
1280 if (cv == D_forecv)
1282 int cx = layer->l_x + cv->c_xoff;
1283 int cy = layer->l_y + cv->c_yoff;
1285 if (cx < cv->c_xs) cx = cv->c_xs;
1286 if (cy < cv->c_ys) cy = cv->c_ys;
1287 if (cx > cv->c_xe) cx = cv->c_xe;
1288 if (cy > cv->c_ye) cy = cv->c_ye;
1290 GotoPos(cx, cy);
1294 for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
1295 layer->l_pause.left[line] = layer->l_pause.right[line] = -1;
1296 olddisplay = display;
1299 void
1300 LayPauseUpdateRegion(layer, xs, xe, ys, ye)
1301 struct layer *layer;
1302 int xs, xe;
1303 int ys, ye;
1305 if (!layer->l_pause.d)
1306 return;
1307 if (ys < 0)
1308 ys = 0;
1309 if (ye >= layer->l_height)
1310 ye = layer->l_height - 1;
1311 if (xe >= layer->l_width)
1312 xe = layer->l_width - 1;
1314 if (layer->l_pause.top == -1 || layer->l_pause.top > ys)
1315 layer->l_pause.top = ys;
1316 if (layer->l_pause.bottom < ye)
1318 layer->l_pause.bottom = ye;
1319 if (layer->l_pause.lines <= ye)
1321 int o = layer->l_pause.lines;
1322 layer->l_pause.lines = ye + 32;
1323 layer->l_pause.left = realloc(layer->l_pause.left, sizeof(int) * layer->l_pause.lines);
1324 layer->l_pause.right = realloc(layer->l_pause.right, sizeof(int) * layer->l_pause.lines);
1325 while (o < layer->l_pause.lines)
1327 layer->l_pause.left[o] = layer->l_pause.right[o] = -1;
1328 o++;
1333 while (ys <= ye)
1335 if (layer->l_pause.left[ys] == -1 || layer->l_pause.left[ys] > xs)
1336 layer->l_pause.left[ys] = xs;
1337 if (layer->l_pause.right[ys] < xe)
1338 layer->l_pause.right[ys] = xe;
1339 ys++;
1343 void
1344 LayerCleanupMemory(layer)
1345 struct layer *layer;
1347 if (layer->l_pause.left)
1348 free(layer->l_pause.left);
1349 if (layer->l_pause.right)
1350 free(layer->l_pause.right);