Add readine-like behaviour for \x17, \x04 in input layer.
[screen-lua.git] / src / layer.c
blobbbd74ee81cd1e056632e8c7597602c9d82ff2bd0
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 2, 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, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 char *s2;
402 int xs2, xe2, y2, len, len2;
403 struct mchar or;
405 if (x + n > l->l_width)
406 n = l->l_width - x;
407 #ifdef HAVE_BRAILLE
408 if (bd.bd_refreshing)
410 BPutStr(l, s, n, r, x, y);
411 return;
413 #endif
414 len = strlen(s);
415 if (len > n)
416 len = n;
417 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
418 for (vp = cv->c_vplist; vp; vp = vp->v_next)
420 y2 = y + vp->v_yoff;
421 if (y2 < vp->v_ys || y2 > vp->v_ye)
422 continue;
423 xs2 = x + vp->v_xoff;
424 xe2 = xs2 + n - 1;
425 if (xs2 < vp->v_xs)
426 xs2 = vp->v_xs;
427 if (xe2 > vp->v_xe)
428 xe2 = vp->v_xe;
429 if (xs2 > xe2)
430 continue;
431 display = cv->c_display;
432 if (D_blocked)
433 continue;
434 GotoPos(xs2, y2);
435 SetRendition(r);
436 len2 = xe2 - (x + vp->v_xoff) + 1;
437 if (len2 > len)
438 len2 = len;
439 PutWinMsg(s, xs2 - x - vp->v_xoff, len2);
440 xs2 = x + vp->v_xoff + len2;
441 if (xs2 < vp->v_xs)
442 xs2 = vp->v_xs;
443 or = D_rend;
444 GotoPos(xs2, y2);
445 SetRendition(&or);
446 while (xs2++ <= xe2)
447 PUTCHARLP(' ');
451 void
452 LClearLine(l, y, xs, xe, bce, ol)
453 struct layer *l;
454 int xs, xe, bce;
455 struct mline *ol;
457 struct canvas *cv;
458 struct viewport *vp;
459 int y2, xs2, xe2;
461 /* check for magic margin condition */
462 if (xs >= l->l_width)
463 xs = l->l_width - 1;
464 if (xe >= l->l_width)
465 xe = l->l_width - 1;
466 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
467 for (vp = cv->c_vplist; vp; vp = vp->v_next)
469 xs2 = xs + vp->v_xoff;
470 xe2 = xe + vp->v_xoff;
471 y2 = y + vp->v_yoff;
472 if (y2 < vp->v_ys || y2 > vp->v_ye)
473 continue;
474 if (xs2 < vp->v_xs)
475 xs2 = vp->v_xs;
476 if (xe2 > vp->v_xe)
477 xe2 = vp->v_xe;
478 if (xs2 > xe2)
479 continue;
480 display = cv->c_display;
481 if (D_blocked)
482 continue;
483 ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
487 void
488 LClearArea(l, xs, ys, xe, ye, bce, uself)
489 struct layer *l;
490 int xs, ys, xe, ye;
491 int bce;
492 int uself;
494 struct canvas *cv;
495 struct viewport *vp;
496 int xs2, ys2, xe2, ye2;
497 #ifdef HAVE_BRAILLE
498 if (bd.bd_refreshing)
499 return;
500 #endif
501 /* check for magic margin condition */
502 if (xs >= l->l_width)
503 xs = l->l_width - 1;
504 if (xe >= l->l_width)
505 xe = l->l_width - 1;
506 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
508 display = cv->c_display;
509 if (D_blocked)
510 continue;
511 for (vp = cv->c_vplist; vp; vp = vp->v_next)
513 xs2 = xs + vp->v_xoff;
514 xe2 = xe + vp->v_xoff;
515 ys2 = ys + vp->v_yoff;
516 ye2 = ye + vp->v_yoff;
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 > vp->v_xe)
522 ys2++;
523 if (xe2 < vp->v_xs)
524 ye2--;
525 if (ys2 < vp->v_ys)
526 ys2 = vp->v_ys;
527 if (ye2 > vp->v_ye)
528 ye2 = vp->v_ye;
529 if (ys2 > ye2)
530 continue;
531 #if 0
532 xcs = vp->v_xoff;
533 xce = l->l_width - 1 + vp->v_xoff;
534 if (xcs < vp->v_xs)
535 xcs = vp->v_xs;
536 if (xce > vp->v_xe)
537 xce = vp->v_xe;
538 if (xcs > xce)
539 continue;
540 if (ys2 != ys + vp->v_yoff)
541 xs2 = xcs;
542 if (ye2 != ye + vp->v_yoff)
543 xe2 = xce;
544 display = cv->c_display;
545 ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself);
546 #else
547 if (xs == 0 || ys2 != ys + vp->v_yoff)
548 xs2 = vp->v_xs;
549 if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
550 xe2 = vp->v_xe;
551 display = cv->c_display;
552 ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself);
553 #endif
558 void
559 LCDisplayLine(l, ml, y, xs, xe, isblank)
560 struct layer *l;
561 struct mline *ml;
562 int y, xs, xe;
563 int isblank;
565 struct canvas *cv;
566 struct viewport *vp;
567 int xs2, xe2, y2;
568 #ifdef HAVE_BRAILLE
569 if (bd.bd_refreshing)
571 BCDisplayLine(l, ml, y, xs, xe, isblank);
572 return;
574 #endif
575 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
577 display = cv->c_display;
578 if (D_blocked)
579 continue;
580 for (vp = cv->c_vplist; vp; vp = vp->v_next)
582 xs2 = xs + vp->v_xoff;
583 xe2 = xe + vp->v_xoff;
584 y2 = y + vp->v_yoff;
585 if (y2 < vp->v_ys || y2 > vp->v_ye)
586 continue;
587 if (xs2 < vp->v_xs)
588 xs2 = vp->v_xs;
589 if (xe2 > vp->v_xe)
590 xe2 = vp->v_xe;
591 if (xs2 > xe2)
592 continue;
593 display = cv->c_display;
594 debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
595 debug1(" mloff = %d\n", -vp->v_xoff);
596 DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
601 void
602 LCDisplayLineWrap(l, ml, y, from, to, isblank)
603 struct layer *l;
604 struct mline *ml;
605 int y, from, to;
606 int isblank;
608 struct mchar nc;
609 copy_mline2mchar(&nc, ml, 0);
610 #ifdef DW_CHARS
611 if (dw_left(ml, 0, l->l_encoding))
613 nc.mbcs = ml->image[1];
614 from++;
616 #endif
617 LWrapChar(l, &nc, y - 1, -1, -1, 0);
618 from++;
619 if (from <= to)
620 LCDisplayLine(l, ml, y, from, to, isblank);
623 void
624 LSetRendition(l, r)
625 struct layer *l;
626 struct mchar *r;
628 struct canvas *cv;
630 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
632 display = cv->c_display;
633 if (D_blocked)
634 continue;
635 SetRendition(r);
639 void
640 LWrapChar(l, c, y, top, bot, ins)
641 struct layer *l;
642 struct mchar *c;
643 int y, top, bot;
644 int ins;
646 struct canvas *cv, *cvlist, *cvlnext;
647 struct viewport *vp, *evp, **vpp;
648 int yy, y2, yy2, top2, bot2;
649 int bce;
651 #ifdef COLOR
652 bce = rend_getbg(c);
653 #else
654 bce = 0;
655 #endif
656 if (y != bot)
658 /* simple case: no scrolling */
660 /* cursor after wrapping */
661 yy = y == l->l_height - 1 ? y : y + 1;
663 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
665 y2 = 0; /* gcc -Wall */
666 display = cv->c_display;
667 if (D_blocked)
668 continue;
669 /* find the viewport of the wrapped character */
670 for (vp = cv->c_vplist; vp; vp = vp->v_next)
672 y2 = y + vp->v_yoff;
673 yy2 = yy + vp->v_yoff;
674 if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
675 break;
677 if (vp == 0)
678 continue; /* nothing to do, character not visible */
679 /* find the viewport of the character at the end of the line*/
680 for (evp = cv->c_vplist; evp; evp = evp->v_next)
681 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)
682 break; /* gotcha! */
683 if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye))
685 /* no wrapping possible */
686 debug("LWrap: can't wrap!\n");
687 cvlist = l->l_cvlist;
688 cvlnext = cv->c_lnext;
689 l->l_cvlist = cv;
690 cv->c_lnext = 0;
691 if (ins)
692 LInsChar(l, c, 0, yy, 0);
693 else
694 LPutChar(l, c, 0, yy);
695 l->l_cvlist = cvlist;
696 cv->c_lnext = cvlnext;
698 else
700 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
704 else
706 /* hard case: scroll up*/
708 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
710 display = cv->c_display;
711 if (D_blocked)
712 continue;
713 /* search for wrap viewport */
714 for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next)
716 yy2 = bot + vp->v_yoff;
717 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)
718 break;
721 if (vp)
723 /* great, can use Wrap on the vp */
724 /* temporarily remove vp from cvlist */
725 *vpp = vp->v_next;
727 if (cv->c_vplist)
729 /* scroll all viewports != vp */
730 cvlist = l->l_cvlist;
731 cvlnext = cv->c_lnext;
732 l->l_cvlist = cv;
733 cv->c_lnext = 0;
734 LScrollV(l, 1, top, bot, bce);
735 if (!vp)
737 if (ins)
738 LInsChar(l, c, 0, bot, 0);
739 else
740 LPutChar(l, c, 0, bot);
742 l->l_cvlist = cvlist;
743 cv->c_lnext = cvlnext;
745 if (vp)
747 /* add vp back to cvlist */
748 *vpp = vp;
749 top2 = top + vp->v_yoff;
750 bot2 = bot + vp->v_yoff;
751 if (top2 < vp->v_ys)
752 top2 = vp->v_ys;
753 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
760 void
761 LCursorVisibility(l, vis)
762 struct layer *l;
763 int vis;
765 struct canvas *cv;
766 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
768 display = cv->c_display;
769 if (D_blocked)
770 continue;
771 if (cv != D_forecv)
772 continue;
773 CursorVisibility(vis);
777 void
778 LSetFlow(l, flow)
779 struct layer *l;
780 int flow;
782 struct canvas *cv;
783 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
785 display = cv->c_display;
786 if (cv != D_forecv)
787 continue;
788 SetFlow(flow);
792 void
793 LKeypadMode(l, on)
794 struct layer *l;
795 int on;
797 struct canvas *cv;
798 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
800 display = cv->c_display;
801 if (D_blocked)
802 continue;
803 if (cv != D_forecv)
804 continue;
805 KeypadMode(on);
809 void
810 LCursorkeysMode(l, on)
811 struct layer *l;
812 int on;
814 struct canvas *cv;
815 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
817 display = cv->c_display;
818 if (D_blocked)
819 continue;
820 if (cv != D_forecv)
821 continue;
822 CursorkeysMode(on);
826 void
827 LMouseMode(l, on)
828 struct layer *l;
829 int on;
831 struct canvas *cv;
832 for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
834 display = cv->c_display;
835 if (D_blocked)
836 continue;
837 if (cv != D_forecv)
838 continue;
839 MouseMode(on);
843 void
844 LClearAll(l, uself)
845 struct layer *l;
846 int uself;
848 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
851 void
852 LRefreshAll(l, isblank)
853 struct layer *l;
854 int isblank;
856 struct layer *oldflayer;
857 int y;
859 debug1("LRefreshAll isblank=%d\n", isblank);
860 oldflayer = flayer;
861 flayer = l;
862 if (!isblank)
863 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0);
864 /* signal full refresh */
865 LayRedisplayLine(-1, -1, -1, 1);
866 for (y = 0; y < l->l_height; y++)
867 LayRedisplayLine(y, 0, l->l_width - 1, 1);
868 flayer = oldflayer;
871 void
872 /*VARARGS2*/
873 #if defined(USEVARARGS) && defined(__STDC__)
874 LMsg(int err, char *fmt, VA_DOTS)
875 #else
876 LMsg(err, fmt, VA_DOTS)
877 int err;
878 char *fmt;
879 VA_DECL
880 #endif
882 VA_LIST(ap)
883 char buf[MAXPATHLEN*2];
884 char *p = buf;
885 struct canvas *cv;
887 VA_START(ap, fmt);
888 fmt = DoNLS(fmt);
889 (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
890 VA_END(ap);
891 if (err)
893 p += strlen(p);
894 *p++ = ':';
895 *p++ = ' ';
896 strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
897 buf[sizeof(buf) - 1] = 0;
899 debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
900 for (display = displays; display; display = display->d_next)
902 for (cv = D_cvlist; cv; cv = cv->c_next)
903 if (cv->c_layer == flayer)
904 break;
905 if (cv == 0)
906 continue;
907 MakeStatus(buf);
912 /*******************************************************************/
913 /*******************************************************************/
916 * Layer creation / removal
919 void
920 KillLayerChain(lay)
921 struct layer *lay;
923 struct canvas *cv, *ncv;
924 struct layer *l, *oldflayer;
926 oldflayer = flayer;
927 debug1("KillLayerChain %#x\n", lay);
928 for (l = lay; l; l = l->l_next)
930 if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
931 break;
932 debug1("- killing %#x\n", l);
933 if (oldflayer == l)
934 oldflayer = 0;
935 for (cv = l->l_cvlist; cv; cv = ncv)
937 ncv = cv->c_lnext;
938 cv->c_layer = 0;
939 cv->c_lnext = 0;
942 flayer = lay;
943 while (flayer != l)
944 ExitOverlayPage();
945 flayer = oldflayer;
951 InitOverlayPage(datasize, lf, block)
952 int datasize;
953 struct LayFuncs *lf;
954 int block;
956 char *data;
957 struct layer *newlay;
958 struct canvas *cv, *cvp, **cvpp;
959 struct win *p;
961 ASSERT(flayer);
963 cv = 0;
964 if (display && D_forecv->c_layer == flayer)
965 cv = D_forecv; /* work only on this cv! */
967 if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0)
969 Msg(0, "No memory for layer struct");
970 return -1;
972 debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
973 data = 0;
974 if (datasize)
976 if ((data = malloc(datasize)) == 0)
978 free((char *)newlay);
979 Msg(0, "No memory for layer data");
980 return -1;
982 bzero(data, datasize);
985 p = Layer2Window(flayer);
987 if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0)))
989 if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0)
990 KillLayerChain(p->w_savelayer);
991 p->w_savelayer = newlay;
994 if (cv && flayer->l_next == 0 && !block)
996 struct display *olddisplay = display;
997 display = cv->c_display;
998 RemoveStatus();
999 display = olddisplay;
1001 /* new branch -> just get canvas vps */
1002 for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
1003 if (cvp == cv)
1004 break;
1005 ASSERT(cvp);
1006 *cvpp = cv->c_lnext;
1007 newlay->l_cvlist = cv;
1008 cv->c_lnext = 0;
1009 cv->c_layer = newlay;
1011 else
1013 LAY_DISPLAYS(flayer, RemoveStatus());
1014 if (block)
1015 debug("layer is blocking\n");
1016 if (block && flayer->l_layfn == &WinLf)
1018 debug("...and is first, so window gets blocked\n");
1019 ASSERT(p->w_blocked == 0);
1020 p->w_blocked++;
1021 newlay->l_blocking = 1;
1023 /* change all canvases */
1024 newlay->l_cvlist = flayer->l_cvlist;
1025 for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
1026 cvp->c_layer = newlay;
1027 flayer->l_cvlist = 0;
1029 newlay->l_width = flayer->l_width;
1030 newlay->l_height = flayer->l_height;
1031 newlay->l_encoding = 0;
1032 newlay->l_layfn = lf;
1033 newlay->l_data = data;
1034 newlay->l_next = flayer;
1035 newlay->l_bottom = flayer->l_bottom;
1036 flayer = newlay;
1037 LayRestore();
1038 return 0;
1041 extern struct layout *layouts;
1043 void
1044 ExitOverlayPage()
1046 struct layer *oldlay;
1047 struct win *p;
1048 int doredisplay = 0;
1049 struct canvas *cv, *ocv;
1050 struct layout *lay;
1052 ASSERT(flayer);
1053 debug1("Exiting layer %#x\n", (unsigned int)flayer);
1054 oldlay = flayer;
1055 if (oldlay->l_data)
1056 free(oldlay->l_data);
1058 p = Layer2Window(flayer);
1060 flayer = oldlay->l_next;
1061 if (flayer->l_layfn == &WinLf)
1063 if (oldlay->l_blocking)
1065 ASSERT(p->w_blocked > 0);
1066 p->w_blocked--;
1067 debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked);
1069 /* don't warp dead layers: check cvlist */
1070 if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist)
1072 debug("warping to top of blocking chain!\n");
1073 /* warp ourself into savelayer */
1074 flayer = p->w_savelayer;
1075 doredisplay = 1;
1078 if (p && p->w_savelayer == oldlay)
1079 p->w_savelayer = flayer;
1080 #ifdef COPY_PASTE
1081 if (p && oldlay == p->w_paster.pa_pastelayer)
1082 p->w_paster.pa_pastelayer = 0;
1083 #endif
1085 for (lay = layouts; lay; lay = lay->lay_next)
1086 for (cv = lay->lay_cvlist; cv; cv = cv->c_next)
1087 if (cv->c_layer == oldlay)
1088 cv->c_layer = flayer;
1090 /* add all canvases back into next layer's canvas list */
1091 for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext)
1093 cv->c_layer = flayer;
1094 ocv = cv;
1096 if (ocv)
1098 cv = flayer->l_cvlist;
1099 ocv->c_lnext = 0;
1100 flayer->l_cvlist = oldlay->l_cvlist;
1101 /* redisplay only the warped cvs */
1102 if (doredisplay)
1103 LRefreshAll(flayer, 0);
1104 ocv->c_lnext = cv;
1106 oldlay->l_cvlist = 0;
1107 free((char *)oldlay);
1108 LayRestore();
1109 LaySetCursor();