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