1 /* Copyright (c) 2008-2017
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  *
7  * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
8  *      Juergen Weigert <jnweiger@immd4.informatik.uni-erlangen.de>
9  *      Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
10  *
11  * Copyright (c) 1987 Oliver Laumann
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program (see the file COPYING); if not, see
25  * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
27  *
28  ****************************************************************
29  */
30 
31 #include <sys/types.h>
32 
33 #include "config.h"
34 #include "screen.h"
35 #include "mark.h"
36 #include "extern.h"
37 #include "braille.h"
38 
39 extern struct display *display, *displays;
40 
41 extern struct mline mline_blank, mline_null;
42 extern struct mchar mchar_blank, mchar_null;
43 
44 extern struct layer *flayer;	/* sigh */
45 extern struct LayFuncs WinLf;
46 extern struct LayFuncs BlankLf;
47 
48 
49 static struct mline *mloff __P((struct mline *, int));
50 
51 /*
52  * Layer subsystem.
53  *
54  * ...here is all the clipping code... beware!
55  *
56  * XXX: add some speedup code!
57  *
58  */
59 
mloff(struct mline * ml,int off)60 static struct mline *mloff(struct mline *ml, int off)
61 {
62   static struct mline mml;
63   if (ml == 0)
64     return 0;
65 
66   mml.image = ml->image + off;
67   mml.attr  = ml->attr  + off;
68 #ifdef FONT
69   mml.font  = ml->font  + off;
70   mml.fontx  = ml->fontx  + off;
71 #endif
72 
73 #ifdef COLOR
74   mml.color = ml->color + off;
75 # ifdef COLORS256
76   mml.colorx = ml->colorx + off;
77 # endif
78 #endif
79 
80   return &mml;
81 }
82 
83 #ifdef UTF8
84 # define RECODE_MCHAR(mc) ((l->l_encoding == UTF8) != (D_encoding == UTF8) ? recode_mchar(mc, l->l_encoding, D_encoding) : (mc))
85 # define RECODE_MLINE(ml) ((l->l_encoding == UTF8) != (D_encoding == UTF8) ? recode_mline(ml, l->l_width, l->l_encoding, D_encoding) : (ml))
86 #else
87 # define RECODE_MCHAR(mc) (mc)
88 # define RECODE_MLINE(ml) (ml)
89 #endif
90 
91 #define FOR_EACH_UNPAUSED_CANVAS(l, fn) for (cv = (l)->l_cvlist; cv; cv = cv->c_lnext) \
92   {	\
93     if ((l)->l_pause.d && cv->c_slorient)	\
94       continue;	\
95     fn	\
96   }
97 
LGotoPos(struct layer * l,int x,int y)98 void LGotoPos(struct layer *l, int x, int y)
99 {
100   struct canvas *cv;
101   struct viewport *vp;
102   int x2, y2;
103 
104   if (l->l_pause.d)
105     LayPauseUpdateRegion(l, x, x, y, y);
106 
107 #ifdef HAVE_BRAILLE
108   if (bd.bd_refreshing)
109     return;
110 #endif
111   FOR_EACH_UNPAUSED_CANVAS(l,
112     {
113       display = cv->c_display;
114       if (D_blocked)
115         continue;
116       if (cv != D_forecv)
117         continue;
118       x2 = x + cv->c_xoff;
119       y2 = y + cv->c_yoff;
120       debug2("---LGotoPos %d %d\n", x2, y2);
121       if (x2 < cv->c_xs)
122         x2 = cv->c_xs;
123       if (y2 < cv->c_ys)
124         y2 = cv->c_ys;
125       if (x2 > cv->c_xe)
126         x2 = cv->c_xe;
127       if (y2 > cv->c_ye)
128         y2 = cv->c_ye;
129       for (vp = cv->c_vplist; vp; vp = vp->v_next) {
130         if (x2 < vp->v_xs || x2 > vp->v_xe)
131           continue;
132         if (y2 < vp->v_ys || y2 > vp->v_ye)
133           continue;
134         GotoPos(x2, y2);
135         break;
136       }
137     }
138   );
139 }
140 
LScrollH(struct layer * l,int n,int y,int xs,int xe,int bce,struct mline * ol)141 void LScrollH(struct layer *l, int n, int y, int xs, int xe, int bce, struct mline *ol)
142 {
143   struct canvas *cv;
144   struct viewport *vp;
145   int y2, xs2, xe2;
146 
147   if (n == 0)
148     return;
149   if (l->l_pause.d)
150     LayPauseUpdateRegion(l, xs, xe, y, y);
151 
152   FOR_EACH_UNPAUSED_CANVAS(l,
153     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
154       y2 = y + vp->v_yoff;
155       if (y2 < vp->v_ys || y2 > vp->v_ye)
156         continue;
157       xs2 = xs + vp->v_xoff;
158       xe2 = xe + vp->v_xoff;
159       if (xs2 < vp->v_xs)
160         xs2 = vp->v_xs;
161       if (xe2 > vp->v_xe)
162         xe2 = vp->v_xe;
163       if (xs2 > xe2)
164         continue;
165       display = cv->c_display;
166       if (D_blocked)
167         continue;
168       ScrollH(y2, xs2, xe2, n, bce, ol ? mloff(ol, -vp->v_xoff) : 0);
169       if (xe2 - xs2 == xe - xs)
170         continue;
171       if (n > 0) {
172         xs2 = xe2 + 1 - n;
173         xe2 = xe + vp->v_xoff - n;
174       }
175       else {
176         xe2 = xs2 - 1 - n;
177         xs2 = xs + vp->v_xoff - n;
178       }
179 
180       if (xs2 < vp->v_xs)
181         xs2 = vp->v_xs;
182       if (xe2 > vp->v_xe)
183         xe2 = vp->v_xe;
184       if (xs2 <= xe2)
185         RefreshArea(xs2, y2, xe2, y2, 1);
186     }
187   );
188 }
189 
LScrollV(struct layer * l,int n,int ys,int ye,int bce)190 void LScrollV(struct layer *l, int n, int ys, int ye, int bce)
191 {
192   struct canvas *cv;
193   struct viewport *vp;
194   int ys2, ye2, xs2, xe2;
195   if (n == 0)
196     return;
197   if (l->l_pause.d)
198     LayPauseUpdateRegion(l, 0, l->l_width - 1, ys, ye);
199   FOR_EACH_UNPAUSED_CANVAS(l,
200     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
201       xs2 = vp->v_xoff;
202       xe2 = l->l_width - 1 + vp->v_xoff;
203       ys2 = ys + vp->v_yoff;
204       ye2 = ye + vp->v_yoff;
205 
206       if (xs2 < vp->v_xs)
207         xs2 = vp->v_xs;
208       if (xe2 > vp->v_xe)
209         xe2 = vp->v_xe;
210       if (ys2 < vp->v_ys)
211         ys2 = vp->v_ys;
212       if (ye2 > vp->v_ye)
213         ye2 = vp->v_ye;
214       if (ys2 > ye2 || xs2 > xe2)
215         continue;
216       display = cv->c_display;
217       if (D_blocked)
218         continue;
219 #if 0
220       ScrollV(xs2, ys2, xe2, ye2, n, bce);
221 #else
222       ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n, bce);
223 #endif
224 
225       debug2("LScrollV: %d %d", ys, ye);
226       debug2(" -> %d %d\n", ys2, ye2);
227       if (ye2 - ys2 == ye - ys)
228         continue;
229       if (n > 0) {
230         ys2 = ye2 + 1 - n;
231         ye2 = ye + vp->v_yoff - n;
232       }
233       else {
234         ye2 = ys2 - 1 - n;
235         ys2 = ys + vp->v_yoff - n;
236       }
237 
238       debug2("LScrollV: - %d %d\n", ys2, ye2);
239       if (ys2 < vp->v_ys)
240         ys2 = vp->v_ys;
241       if (ye2 > vp->v_ye)
242         ye2 = vp->v_ye;
243       debug2("LScrollV: - %d %d\n", ys2, ye2);
244       if (ys2 <= ye2)
245         RefreshArea(xs2, ys2, xe2, ye2, 1);
246     }
247   );
248 }
249 
LInsChar(struct layer * l,struct mchar * c,int x,int y,struct mline * ol)250 void LInsChar(struct layer *l, struct mchar *c, int x, int y, struct mline *ol)
251 {
252   struct canvas *cv;
253   struct viewport *vp;
254   int xs2, xe2, y2, f;
255   struct mchar *c2, cc;
256   struct mline *rol;
257 
258   if (l->l_pause.d)
259     LayPauseUpdateRegion(l, x, l->l_width - 1, y, y);
260   FOR_EACH_UNPAUSED_CANVAS(l,
261     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
262       y2 = y + vp->v_yoff;
263       if (y2 < vp->v_ys || y2 > vp->v_ye)
264         continue;
265       xs2 = x + vp->v_xoff;
266       xe2 = l->l_width - 1 + vp->v_xoff;
267       c2 = c;
268       f = 0;
269       if (xs2 < vp->v_xs) {
270         xs2 = vp->v_xs;
271         c2 = &mchar_blank;
272         if (ol) {
273           int i = xs2 - vp->v_xoff - 1;
274           if (i >= 0 && i < l->l_width) {
275             copy_mline2mchar(&cc, ol, i);
276             c2 = &cc;
277           }
278         }
279        else
280         f = 1;
281       }
282 
283       if (xe2 > vp->v_xe)
284         xe2 = vp->v_xe;
285       if (xs2 > xe2)
286         continue;
287       display = cv->c_display;
288       if (D_blocked)
289         continue;
290       rol = RECODE_MLINE(ol);
291       InsChar(RECODE_MCHAR(c2), xs2, xe2, y2, mloff(rol, -vp->v_xoff));
292       if (f)
293         RefreshArea(xs2, y2, xs2, y2, 1);
294     }
295   );
296 }
297 
298 
LPutChar(struct layer * l,struct mchar * c,int x,int y)299 void LPutChar(struct layer *l, struct mchar *c, int x, int y)
300 {
301   struct canvas *cv;
302   struct viewport *vp;
303   int x2, y2;
304 
305 #ifdef HAVE_BRAILLE
306   if (bd.bd_refreshing) {
307     BPutChar(l, c, x, y);
308     return;
309   }
310 #endif
311 
312   if (l->l_pause.d)
313     LayPauseUpdateRegion(l, x,
314 
315 #ifdef DW_CHARS
316   x + (c->mbcs ? 1 : 0)
317 #else
318   x
319 #endif
320   , y, y);
321 
322 
323   FOR_EACH_UNPAUSED_CANVAS(l,
324     {
325       display = cv->c_display;
326       if (D_blocked)
327         continue;
328       for (vp = cv->c_vplist; vp; vp = vp->v_next) {
329         y2 = y + vp->v_yoff;
330         if (y2 < vp->v_ys || y2 > vp->v_ye)
331           continue;
332         x2 = x + vp->v_xoff;
333         if (x2 < vp->v_xs || x2 > vp->v_xe)
334           continue;
335         PutChar(RECODE_MCHAR(c), x2, y2);
336         break;
337       }
338     }
339   );
340 }
341 
342 
LPutStr(struct layer * l,char * s,int n,struct mchar * r,int x,int y)343 void LPutStr(struct layer *l, char *s, int n, struct mchar *r, int x, int y)
344 {
345   struct canvas *cv;
346   struct viewport *vp;
347   char *s2;
348   int xs2, xe2, y2;
349 
350   if (x + n > l->l_width)
351     n = l->l_width - x;
352 
353 #ifdef HAVE_BRAILLE
354   if (bd.bd_refreshing) {
355     BPutStr(l, s, n, r, x, y);
356     return;
357   }
358 #endif
359 
360   if (l->l_pause.d)
361     LayPauseUpdateRegion(l, x, x + n - 1, y, y);
362 
363   FOR_EACH_UNPAUSED_CANVAS(l,
364     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
365       y2 = y + vp->v_yoff;
366       if (y2 < vp->v_ys || y2 > vp->v_ye)
367         continue;
368       xs2 = x + vp->v_xoff;
369       xe2 = xs2 + n - 1;
370       if (xs2 < vp->v_xs)
371         xs2 = vp->v_xs;
372       if (xe2 > vp->v_xe)
373         xe2 = vp->v_xe;
374       if (xs2 > xe2)
375         continue;
376       display = cv->c_display;
377       if (D_blocked)
378         continue;
379       GotoPos(xs2, y2);
380       SetRendition(r);
381       s2 = s + xs2 - x - vp->v_xoff;
382 
383 #ifdef UTF8
384       if (D_encoding == UTF8 && l->l_encoding != UTF8 && (r->font || r->fontx || l->l_encoding)) {
385         struct mchar mc;
386         mc = *r;
387         while (xs2 <= xe2) {
388           mc.image = *s2++;
389           PutChar(RECODE_MCHAR(&mc), xs2++, y2);
390         }
391         continue;
392       }
393 #endif
394 
395       while (xs2++ <= xe2)
396         PUTCHARLP(*s2++);
397     }
398   );
399 }
400 
401 
LPutWinMsg(struct layer * l,char * s,int n,struct mchar * r,int x,int y)402 void LPutWinMsg(struct layer *l, char *s, int n, struct mchar *r, int x, int y)
403 {
404   struct canvas *cv;
405   struct viewport *vp;
406   int xs2, xe2, y2, len, len2;
407   struct mchar or;
408 
409   if (x + n > l->l_width)
410     n = l->l_width - x;
411 
412 #ifdef HAVE_BRAILLE
413   if (bd.bd_refreshing) {
414     BPutStr(l, s, n, r, x, y);
415     return;
416   }
417 #endif
418 
419   if (l->l_pause.d)
420     LayPauseUpdateRegion(l, x, x + n - 1, y, y);
421 
422   len = strlen(s);
423   if (len > n)
424     len = n;
425 
426   FOR_EACH_UNPAUSED_CANVAS(l,
427     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
428       y2 = y + vp->v_yoff;
429       if (y2 < vp->v_ys || y2 > vp->v_ye)
430         continue;
431       xs2 = x + vp->v_xoff;
432       xe2 = xs2 + n - 1;
433       if (xs2 < vp->v_xs)
434         xs2 = vp->v_xs;
435       if (xe2 > vp->v_xe)
436         xe2 = vp->v_xe;
437       if (xs2 > xe2)
438         continue;
439       display = cv->c_display;
440       if (D_blocked)
441         continue;
442       GotoPos(xs2, y2);
443       SetRendition(r);
444       len2 = xe2 - (x + vp->v_xoff) + 1;
445       if (len2 > len)
446         len2 = len;
447       PutWinMsg(s, xs2 - x - vp->v_xoff, len2);
448       xs2 = x + vp->v_xoff + len2;
449       if (xs2 < vp->v_xs)
450         xs2 = vp->v_xs;
451       or = D_rend;
452       GotoPos(xs2, y2);
453       SetRendition(&or);
454       while (xs2++ <= xe2)
455         PUTCHARLP(' ');
456     }
457   );
458 }
459 
460 
LClearLine(struct layer * l,int y,int xs,int xe,int bce,struct mline * ol)461 void LClearLine(struct layer *l, int y, int xs, int xe, int bce, struct mline *ol)
462 {
463   struct canvas *cv;
464   struct viewport *vp;
465   int y2, xs2, xe2;
466 
467   /* check for magic margin condition */
468   if (xs >= l->l_width)
469     xs = l->l_width - 1;
470   if (xe >= l->l_width)
471     xe = l->l_width - 1;
472   if (l->l_pause.d)
473       LayPauseUpdateRegion(l, xs, xe, y, y);
474 
475   FOR_EACH_UNPAUSED_CANVAS(l,
476     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
477       xs2 = xs + vp->v_xoff;
478       xe2 = xe + vp->v_xoff;
479       y2  = y + vp->v_yoff;
480       if (y2 < vp->v_ys || y2 > vp->v_ye)
481         continue;
482       if (xs2 < vp->v_xs)
483         xs2 = vp->v_xs;
484       if (xe2 > vp->v_xe)
485         xe2 = vp->v_xe;
486       if (xs2 > xe2)
487         continue;
488       display = cv->c_display;
489       if (D_blocked)
490         continue;
491       ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce);
492     }
493   );
494 }
495 
LClearArea(struct layer * l,int xs,int ys,int xe,int ye,int bce,int uself)496 void LClearArea(struct layer *l, int xs, int ys, int xe, int ye, int bce, int uself)
497 {
498   struct canvas *cv;
499   struct viewport *vp;
500   int xs2, ys2, xe2, ye2;
501 
502 #ifdef HAVE_BRAILLE
503   if (bd.bd_refreshing)
504     return;
505 #endif
506 
507   /* Check for zero-height window */
508   if (ys < 0 || ye < ys)
509     return;
510 
511   /* check for magic margin condition */
512   if (xs >= l->l_width)
513     xs = l->l_width - 1;
514   if (xe >= l->l_width)
515     xe = l->l_width - 1;
516   if (l->l_pause.d)
517     LayPauseUpdateRegion(l, xs, xe, ys, ye);
518 
519   FOR_EACH_UNPAUSED_CANVAS(l,
520     {
521       display = cv->c_display;
522       if (D_blocked)
523         continue;
524       for (vp = cv->c_vplist; vp; vp = vp->v_next) {
525         xs2 = xs + vp->v_xoff;
526         xe2 = xe + vp->v_xoff;
527         ys2 = ys + vp->v_yoff;
528         ye2 = ye + vp->v_yoff;
529 
530         if (xs2 < vp->v_xs)
531           xs2 = vp->v_xs;
532         if (xe2 > vp->v_xe)
533           xe2 = vp->v_xe;
534         if (xs2 > vp->v_xe)
535           ys2++;
536         if (xe2 < vp->v_xs)
537           ye2--;
538         if (ys2 < vp->v_ys)
539           ys2 = vp->v_ys;
540         if (ye2 > vp->v_ye)
541           ye2 = vp->v_ye;
542         if (ys2 > ye2)
543           continue;
544 #if 0
545         xcs = vp->v_xoff;
546         xce = l->l_width - 1 + vp->v_xoff;
547         if (xcs < vp->v_xs)
548           xcs = vp->v_xs;
549         if (xce > vp->v_xe)
550           xce = vp->v_xe;
551         if (xcs > xce)
552           continue;
553         if (ys2 != ys + vp->v_yoff)
554           xs2 = xcs;
555         if (ye2 != ye + vp->v_yoff)
556           xe2 = xce;
557         display = cv->c_display;
558         ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself);
559 #else
560 
561         if (xs == 0 || ys2 != ys + vp->v_yoff)
562           xs2 = vp->v_xs;
563         if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff)
564           xe2 = vp->v_xe;
565         display = cv->c_display;
566         ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself);
567 
568         if (xe == l->l_width - 1 && xe2 > vp->v_xoff + xe) {
569           int y;
570           SetRendition(&mchar_blank);
571           for (y = ys2; y <= ye2; y++) {
572             GotoPos(xe + vp->v_xoff + 1, y);
573             PUTCHARLP('|');
574           }
575         }
576 #endif
577       }
578     }
579   );
580 }
581 
582 
LCDisplayLine(struct layer * l,struct mline * ml,int y,int xs,int xe,int isblank)583 void LCDisplayLine(struct layer *l, struct mline *ml, int y, int xs, int xe, int isblank)
584 {
585   struct canvas *cv;
586   struct viewport *vp;
587   int xs2, xe2, y2;
588 
589 #ifdef HAVE_BRAILLE
590   if (bd.bd_refreshing) {
591     BCDisplayLine(l, ml, y, xs, xe, isblank);
592     return;
593   }
594 #endif
595 
596   if (l->l_pause.d)
597     LayPauseUpdateRegion(l, xs, xe, y, y);
598 
599   FOR_EACH_UNPAUSED_CANVAS(l,
600     {
601       display = cv->c_display;
602       if (D_blocked)
603         continue;
604       for (vp = cv->c_vplist; vp; vp = vp->v_next) {
605         xs2 = xs + vp->v_xoff;
606         xe2 = xe + vp->v_xoff;
607         y2  = y + vp->v_yoff;
608         if (y2 < vp->v_ys || y2 > vp->v_ye)
609           continue;
610         if (xs2 < vp->v_xs)
611           xs2 = vp->v_xs;
612         if (xe2 > vp->v_xe)
613           xe2 = vp->v_xe;
614         if (xs2 > xe2)
615           continue;
616         display = cv->c_display;
617         debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2);
618         debug1("  mloff = %d\n", -vp->v_xoff);
619         DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2);
620       }
621     }
622   );
623 }
624 
625 
LCDisplayLineWrap(struct layer * l,struct mline * ml,int y,int from,int to,int isblank)626 void LCDisplayLineWrap(struct layer *l, struct mline *ml, int y, int from, int to, int isblank)
627 {
628   struct mchar nc;
629   copy_mline2mchar(&nc, ml, 0);
630 
631 #ifdef DW_CHARS
632   if (dw_left(ml, 0, l->l_encoding)) {
633     nc.mbcs = ml->image[1];
634     from++;
635   }
636 #endif
637 
638   LWrapChar(l, &nc, y - 1, -1, -1, 0);
639   from++;
640   if (from <= to)
641     LCDisplayLine(l, ml, y, from, to, isblank);
642 }
643 
644 
LSetRendition(struct layer * l,struct mchar * r)645 void LSetRendition(struct layer *l, struct mchar *r)
646 {
647   struct canvas *cv;
648 
649   for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
650     display = cv->c_display;
651     if (D_blocked)
652       continue;
653     SetRendition(r);
654   }
655 }
656 
657 
LWrapChar(struct layer * l,struct mchar * c,int y,int top,int bot,int ins)658 void LWrapChar(struct layer *l, struct mchar *c, int y, int top, int bot, int ins)
659 {
660   struct canvas *cv, *cvlist, *cvlnext;
661   struct viewport *vp, *evp, **vpp;
662   int yy, y2, yy2, top2, bot2;
663   int bce;
664 
665   if (l->l_pause.d)
666     /* XXX: 'y'? */
667     LayPauseUpdateRegion(l, 0, l->l_width - 1, top, bot);
668 
669 #ifdef COLOR
670   bce = rend_getbg(c);
671 #else
672   bce = 0;
673 #endif
674 
675   if (y != bot) {
676   /* simple case: no scrolling */
677   /* cursor after wrapping */
678     yy = y == l->l_height - 1 ? y : y + 1;
679 
680     FOR_EACH_UNPAUSED_CANVAS(l,
681     {
682       y2 = 0;       /* gcc -Wall */
683       display = cv->c_display;
684       if (D_blocked)
685         continue;
686 
687       /* find the viewport of the wrapped character */
688       for (vp = cv->c_vplist; vp; vp = vp->v_next) {
689         y2 =  y + vp->v_yoff;
690         yy2 = yy + vp->v_yoff;
691         if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe)
692           break;
693       }
694 
695       if (vp == 0)
696         continue;	/* nothing to do, character not visible */
697 
698       /* find the viewport of the character at the end of the line*/
699       for (evp = cv->c_vplist; evp; evp = evp->v_next)
700         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)
701           break;	/* gotcha! */
702 
703       if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye)) {
704         /* no wrapping possible */
705         debug("LWrap: can't wrap!\n");
706         cvlist = l->l_cvlist;
707         cvlnext = cv->c_lnext;
708         l->l_cvlist = cv;
709         cv->c_lnext = 0;
710 
711         if (ins)
712           LInsChar(l, c, 0, yy, 0);
713         else
714           LPutChar(l, c, 0, yy);
715 
716         l->l_cvlist = cvlist;
717         cv->c_lnext = cvlnext;
718       }
719       else
720         WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins);
721     });
722   }
723   else
724   {
725   /* hard case: scroll up*/
726     FOR_EACH_UNPAUSED_CANVAS(l,
727     {
728       display = cv->c_display;
729       if (D_blocked)
730         continue;
731 
732       /* search for wrap viewport */
733       for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next) {
734         yy2 = bot + vp->v_yoff;
735         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)
736           break;
737       }
738 
739       if (vp) {
740         /* great, can use Wrap on the vp */
741         /* temporarily remove vp from cvlist */
742         *vpp = vp->v_next;
743       }
744 
745       if (cv->c_vplist) {
746         /* scroll all viewports != vp */
747         cvlist = l->l_cvlist;
748         cvlnext = cv->c_lnext;
749         l->l_cvlist = cv;
750         cv->c_lnext = 0;
751         LScrollV(l, 1, top, bot, bce);
752         if (!vp) {
753           if (ins)
754             LInsChar(l, c, 0, bot, 0);
755           else
756             LPutChar(l, c, 0, bot);
757         }
758 
759         l->l_cvlist = cvlist;
760         cv->c_lnext = cvlnext;
761       }
762       if (vp) {
763         /* add vp back to cvlist */
764         *vpp = vp;
765         top2 = top + vp->v_yoff;
766         bot2 = bot + vp->v_yoff;
767         if (top2 < vp->v_ys)
768           top2 = vp->v_ys;
769         WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins);
770       }
771     });
772   }
773 }
774 
775 
LCursorVisibility(struct layer * l,int vis)776 void LCursorVisibility(struct layer *l, int vis)
777 {
778   struct canvas *cv;
779   for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
780     display = cv->c_display;
781     if (D_blocked)
782       continue;
783     if (cv != D_forecv)
784       continue;
785     CursorVisibility(vis);
786   }
787 }
788 
789 
LSetFlow(struct layer * l,int flow)790 void LSetFlow(struct layer *l, int flow)
791 {
792   struct canvas *cv;
793   for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
794     display = cv->c_display;
795     if (cv != D_forecv)
796       continue;
797     SetFlow(flow);
798   }
799 }
800 
801 
LKeypadMode(struct layer * l,int on)802 void LKeypadMode(struct layer *l, int on)
803 {
804   struct canvas *cv;
805   for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
806     display = cv->c_display;
807     if (D_blocked)
808       continue;
809     if (cv != D_forecv)
810       continue;
811     KeypadMode(on);
812   }
813 }
814 
815 
LCursorkeysMode(struct layer * l,int on)816 void LCursorkeysMode(struct layer *l, int on)
817 {
818   struct canvas *cv;
819   for (cv = l->l_cvlist; cv; cv = cv->c_lnext) {
820     display = cv->c_display;
821     if (D_blocked)
822       continue;
823     if (cv != D_forecv)
824       continue;
825     CursorkeysMode(on);
826   }
827 }
828 
829 
LMouseMode(struct layer * l,int on)830 void LMouseMode(struct layer *l, int on)
831 {
832   struct canvas *cv;
833   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);
840   }
841 }
842 
LClearAll(struct layer * l,int uself)843 void LClearAll(struct layer *l, int uself)
844 {
845   LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself);
846 }
847 
848 
LRefreshAll(struct layer * l,int isblank)849 void LRefreshAll(struct layer *l, int isblank)
850 {
851   struct layer *oldflayer;
852   int y;
853 
854   debug1("LRefreshAll isblank=%d\n", isblank);
855   oldflayer = flayer;
856   flayer = l;
857   if (!isblank)
858     LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0);
859   /* signal full refresh */
860   LayRedisplayLine(-1, -1, -1, 1);
861   for (y = 0; y < l->l_height; y++)
862     LayRedisplayLine(y, 0, l->l_width - 1, 1);
863   flayer = oldflayer;
864 }
865 
866 void
867 /*VARARGS2*/
868 #if defined(USEVARARGS) && defined(__STDC__)
LMsg(int err,const char * fmt,VA_DOTS)869 LMsg(int err, const char *fmt, VA_DOTS)
870 #else
871 LMsg(err, fmt, VA_DOTS)
872 int err;
873 const char *fmt;
874 VA_DECL
875 #endif
876 {
877   VA_LIST(ap)
878   char buf[MAXPATHLEN*2];
879   char *p = buf;
880   struct canvas *cv;
881 
882   VA_START(ap, fmt);
883   fmt = DoNLS(fmt);
884   (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap));
885   VA_END(ap);
886 
887   if (err) {
888     p += strlen(p);
889     *p++ = ':';
890     *p++ = ' ';
891     strncpy(p, strerror(err), buf + sizeof(buf) - p - 1);
892     buf[sizeof(buf) - 1] = 0;
893   }
894 
895   debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer);
896   for (display = displays; display; display = display->d_next) {
897     for (cv = D_cvlist; cv; cv = cv->c_next)
898       if (cv->c_layer == flayer)
899         break;
900 
901     if (cv == 0)
902       continue;
903     MakeStatus(buf);
904   }
905 }
906 
907 void
LExtMouseMode(l,on)908 LExtMouseMode(l, on)
909 struct layer *l;
910 int on;
911 {
912   struct canvas *cv;
913   for (cv = l->l_cvlist; cv; cv = cv->c_lnext)
914     {
915       display = cv->c_display;
916       if (D_blocked)
917 	continue;
918       if (cv != D_forecv)
919 	continue;
920       ExtMouseMode(on);
921     }
922 }
923 
924 
925 /*******************************************************************/
926 /*******************************************************************/
927 
928 /*
929  *  Layer creation / removal
930  */
931 
KillLayerChain(struct layer * lay)932 void KillLayerChain(struct layer *lay)
933 {
934   struct canvas *cv, *ncv;
935   struct layer *l, *oldflayer;
936 
937   oldflayer = flayer;
938   debug1("KillLayerChain %#x\n", lay);
939   for (l = lay; l; l = l->l_next) {
940     if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf)
941       break;
942     debug1("- killing %#x\n", l);
943     if (oldflayer == l)
944       oldflayer = 0;
945     for (cv = l->l_cvlist; cv; cv = ncv) {
946       ncv = cv->c_lnext;
947       cv->c_layer = 0;
948       cv->c_lnext = 0;
949     }
950   }
951   flayer = lay;
952   while (flayer != l)
953     ExitOverlayPage();
954   flayer = oldflayer;
955 }
956 
957 
958 
InitOverlayPage(int datasize,struct LayFuncs * lf,int block)959 int InitOverlayPage(int datasize, struct LayFuncs *lf, int block)
960 {
961   char *data;
962   struct layer *newlay;
963   struct canvas *cv, *cvp, **cvpp;
964   struct win *p;
965 
966   ASSERT(flayer);
967 
968   cv = 0;
969   if (display && D_forecv->c_layer == flayer)
970     cv = D_forecv;	/* work only on this cv! */
971 
972   if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0) {
973     Msg(0, "No memory for layer struct");
974       return -1;
975   }
976   debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay);
977   data = 0;
978   if (datasize) {
979     if ((data = calloc(1, datasize)) == 0) {
980       free((char *)newlay);
981       Msg(0, "No memory for layer data");
982       return -1;
983     }
984   }
985   p = Layer2Window(flayer);
986 
987   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;
991   }
992 
993   if (cv && flayer->l_next == 0 && !block) {
994     struct display *olddisplay = display;
995     display = cv->c_display;
996     RemoveStatus();
997     display = olddisplay;
998 
999     /* new branch -> just get canvas vps */
1000     for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext)
1001       if (cvp == cv)
1002         break;
1003 
1004     ASSERT(cvp);
1005     *cvpp = cv->c_lnext;
1006     newlay->l_cvlist = cv;
1007     cv->c_lnext = 0;
1008     cv->c_layer = newlay;
1009   }
1010   else {
1011     LAY_DISPLAYS(flayer, RemoveStatus());
1012     if (block)
1013       debug("layer is blocking\n");
1014     if (block && flayer->l_layfn == &WinLf) {
1015       debug("...and is first, so window gets blocked\n");
1016       ASSERT(p->w_blocked == 0);
1017       p->w_blocked++;
1018       newlay->l_blocking = 1;
1019     }
1020 
1021     /* change all canvases */
1022     newlay->l_cvlist = flayer->l_cvlist;
1023 
1024     for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext)
1025       cvp->c_layer = newlay;
1026     flayer->l_cvlist = 0;
1027   }
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;
1038 }
1039 
1040 
1041 extern struct layout *layouts;
1042 
ExitOverlayPage()1043 void ExitOverlayPage()
1044 {
1045   struct layer *oldlay;
1046   struct win *p;
1047   int doredisplay = 0;
1048   struct canvas *cv, *ocv;
1049   struct layout *lay;
1050 
1051   ASSERT(flayer);
1052   debug1("Exiting layer %#x\n", (unsigned int)flayer);
1053   oldlay = flayer;
1054   if (oldlay->l_data) {
1055     if (oldlay->l_layfn->lf_LayFree)
1056       LayFree(oldlay->l_data);
1057         free(oldlay->l_data);
1058   }
1059   p = Layer2Window(flayer);
1060 
1061   flayer = oldlay->l_next;
1062   if (flayer->l_layfn == &WinLf) {
1063     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);
1067     }
1068 
1069     /* don't warp dead layers: check cvlist */
1070     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;
1075     }
1076   }
1077 
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
1084 
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;
1089 
1090   /* add all canvases back into next layer's canvas list */
1091   for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext) {
1092     cv->c_layer = flayer;
1093     ocv = cv;
1094   }
1095   if (ocv) {
1096     cv = flayer->l_cvlist;
1097     ocv->c_lnext = 0;
1098     flayer->l_cvlist = oldlay->l_cvlist;
1099 
1100     /* redisplay only the warped cvs */
1101     if (doredisplay)
1102       LRefreshAll(flayer, 0);
1103     ocv->c_lnext = cv;
1104   }
1105   oldlay->l_cvlist = 0;
1106   LayerCleanupMemory(oldlay);
1107   free((char *)oldlay);
1108   LayRestore();
1109   LaySetCursor();
1110 }
1111 
LayProcessMouse(struct layer * l,unsigned char ch)1112 int LayProcessMouse(struct layer *l, unsigned char ch)
1113 {
1114   /* XXX: Make sure the layer accepts mouse events */
1115   int len;
1116   if (l->l_mouseevent.len >= sizeof(l->l_mouseevent.buffer))
1117     return -1;
1118 
1119   len = l->l_mouseevent.len++;
1120   l->l_mouseevent.buffer[len] = (len > 0 ? ch - 33 : ch);
1121   return (l->l_mouseevent.len == sizeof(l->l_mouseevent.buffer));
1122 }
1123 
LayProcessMouseSwitch(struct layer * l,int s)1124 void LayProcessMouseSwitch(struct layer *l, int s)
1125 {
1126   if ((l->l_mouseevent.start = s))
1127     l->l_mouseevent.len = 0;
1128 }
1129 
1130 
LayPause(struct layer * layer,int pause)1131 void LayPause(struct layer *layer, int pause)
1132 {
1133   struct canvas *cv;
1134   int line;
1135   struct win *win;
1136   pause = !!pause;
1137 
1138   if (layer->l_pause.d == pause)
1139     return;
1140 
1141   if ((layer->l_pause.d = pause)) {
1142     /* Start pausing */
1143     layer->l_pause.top = layer->l_pause.bottom = -1;
1144     return;
1145   }
1146 
1147   /* Unpause. So refresh the regions in the displays! */
1148   if (layer->l_pause.top == -1 && layer->l_pause.bottom == -1)
1149     return;
1150 
1151   if (layer->l_layfn == &WinLf)  /* Currently, this will always be the case! */
1152     win = layer->l_data;
1153   else
1154     win = NULL;
1155 
1156   for (cv = layer->l_cvlist; cv; cv = cv->c_lnext) {
1157     struct viewport *vp;
1158 
1159     if (!cv->c_slorient)
1160       continue;              /* Wasn't split, so already updated. */
1161     display = cv->c_display;
1162     for (vp = cv->c_vplist; vp; vp = vp->v_next) {
1163       for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++) {
1164         int xs, xe;
1165         if (line + vp->v_yoff >= vp->v_ys && line + vp->v_yoff <= vp->v_ye &&
1166              ((xs = layer->l_pause.left[line]) >= 0) &&
1167              ((xe = layer->l_pause.right[line]) >= 0)) {
1168            xs += vp->v_xoff;
1169            xe += vp->v_xoff;
1170 
1171           if (xs < vp->v_xs) xs = vp->v_xs;
1172           if (xe > vp->v_xe) xe = vp->v_xe;
1173 
1174 #if defined(DW_CHARS) && defined(UTF8)
1175           if (layer->l_encoding == UTF8 && xe < vp->v_xe && win) {
1176             struct mline *ml = win->w_mlines + line;
1177             if (dw_left(ml, xe, UTF8))
1178               xe++;
1179           }
1180 #endif
1181 
1182           if (xs <= xe)
1183             RefreshLine(line + vp->v_yoff, xs, xe, 0);
1184         }
1185       }
1186     }
1187 
1188     if (cv == D_forecv) {
1189       int cx = layer->l_x + cv->c_xoff;
1190       int cy = layer->l_y + cv->c_yoff;
1191 
1192       if (cx < cv->c_xs) cx = cv->c_xs;
1193       if (cy < cv->c_ys) cy = cv->c_ys;
1194       if (cx > cv->c_xe) cx = cv->c_xe;
1195       if (cy > cv->c_ye) cy = cv->c_ye;
1196 
1197       GotoPos(cx, cy);
1198     }
1199   }
1200 
1201   for (line = layer->l_pause.top; line <= layer->l_pause.bottom; line++)
1202     layer->l_pause.left[line] = layer->l_pause.right[line] = -1;
1203 }
1204 
LayPauseUpdateRegion(struct layer * layer,int xs,int xe,int ys,int ye)1205 void LayPauseUpdateRegion(struct layer *layer, int xs, int xe, int ys, int ye)
1206 {
1207   if (!layer->l_pause.d)
1208     return;
1209   if (ys < 0)
1210     ys = 0;
1211   if (ye >= layer->l_height)
1212     ye = layer->l_height - 1;
1213   if (xe >= layer->l_width)
1214     xe = layer->l_width - 1;
1215 
1216   if (layer->l_pause.top == -1 || layer->l_pause.top > ys)
1217     layer->l_pause.top = ys;
1218   if (layer->l_pause.bottom < ye) {
1219     layer->l_pause.bottom = ye;
1220 
1221     if (layer->l_pause.lines <= ye) {
1222       int o = layer->l_pause.lines;
1223       layer->l_pause.lines = ye + 32;
1224       layer->l_pause.left = realloc(layer->l_pause.left, sizeof(int) * layer->l_pause.lines);
1225       layer->l_pause.right = realloc(layer->l_pause.right, sizeof(int) * layer->l_pause.lines);
1226       while (o < layer->l_pause.lines) {
1227         layer->l_pause.left[o] = layer->l_pause.right[o] = -1;
1228         o++;
1229       }
1230     }
1231   }
1232   while (ys <= ye) {
1233     if (layer->l_pause.left[ys] == -1 || layer->l_pause.left[ys] > xs)
1234     layer->l_pause.left[ys] = xs;
1235       if (layer->l_pause.right[ys] < xe)
1236     layer->l_pause.right[ys] = xe;
1237       ys++;
1238   }
1239 }
1240 
LayerCleanupMemory(struct layer * layer)1241 void LayerCleanupMemory(struct layer *layer)
1242 {
1243   if (layer->l_pause.left)
1244     free(layer->l_pause.left);
1245   if (layer->l_pause.right)
1246     free(layer->l_pause.right);
1247 }
1248