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 5 * 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. 10 * 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. 15 * 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 20 * 21 **************************************************************** 22 */ 23 24#include <sys/types.h> 25 26#include "config.h" 27#include "screen.h" 28#include "mark.h" 29#include "extern.h" 30#include "braille.h" 31 32extern struct display *display, *displays; 33 34extern struct mline mline_blank, mline_null; 35extern struct mchar mchar_blank, mchar_null; 36 37extern struct layer *flayer; /* sigh */ 38extern struct LayFuncs WinLf; 39extern struct LayFuncs BlankLf; 40 41 42static struct mline *mloff __P((struct mline *, int)); 43 44/* 45 * Layer subsystem. 46 * 47 * ...here is all the clipping code... beware! 48 * 49 * XXX: add some speedup code! 50 * 51 */ 52 53static struct mline * 54mloff(ml, off) 55struct mline *ml; 56int off; 57{ 58 static struct mline mml; 59 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; 74} 75 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 83 84 85void 86LGotoPos(l, x, y) 87struct layer *l; 88int x, y; 89{ 90 struct canvas *cv; 91 struct viewport *vp; 92 int x2, y2; 93 94#ifdef HAVE_BRAILLE 95 if (bd.bd_refreshing) 96 return; 97#endif 98 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 99 { 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) 117 { 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; 124 } 125 } 126} 127 128void 129LScrollH(l, n, y, xs, xe, bce, ol) 130struct layer *l; 131int n, y, xs, xe; 132int bce; 133struct mline *ol; 134{ 135 struct canvas *cv; 136 struct viewport *vp; 137 int y2, xs2, xe2; 138 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) 143 { 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) 162 { 163 xs2 = xe2 + 1 - n; 164 xe2 = xe + vp->v_xoff - n; 165 } 166 else 167 { 168 xe2 = xs2 - 1 - n; 169 xs2 = xs + vp->v_xoff - n; 170 } 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); 177 } 178} 179 180void 181LScrollV(l, n, ys, ye, bce) 182struct layer *l; 183int n; 184int ys, ye; 185int bce; 186{ 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) 194 { 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) 222 { 223 ys2 = ye2 + 1 - n; 224 ye2 = ye + vp->v_yoff - n; 225 } 226 else 227 { 228 ye2 = ys2 - 1 - n; 229 ys2 = ys + vp->v_yoff - n; 230 } 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); 239 } 240} 241 242void 243LInsChar(l, c, x, y, ol) 244struct layer *l; 245struct mchar *c; 246int x, y; 247struct mline *ol; 248{ 249 struct canvas *cv; 250 struct viewport *vp; 251 int xs2, xe2, y2, f; 252 struct mchar *c2, cc; 253 struct mline *rol; 254 255 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 256 for (vp = cv->c_vplist; vp; vp = vp->v_next) 257 { 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) 266 { 267 xs2 = vp->v_xs; 268 c2 = &mchar_blank; 269 if (ol) 270 { 271 int i; 272 i = xs2 - vp->v_xoff - 1; 273 if (i >= 0 && i < l->l_width) 274 { 275 copy_mline2mchar(&cc, ol, i); 276 c2 = &cc; 277 } 278 } 279 else 280 f = 1; 281 } 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); 293 } 294} 295 296void 297LPutChar(l, c, x, y) 298struct layer *l; 299struct mchar *c; 300int x, y; 301{ 302 struct canvas *cv; 303 struct viewport *vp; 304 int x2, y2; 305#ifdef HAVE_BRAILLE 306 if (bd.bd_refreshing) 307 { 308 BPutChar(l, c, x, y); 309 return; 310 } 311#endif 312 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 313 { 314 display = cv->c_display; 315 if (D_blocked) 316 continue; 317 for (vp = cv->c_vplist; vp; vp = vp->v_next) 318 { 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; 327 } 328 } 329} 330 331void 332LPutStr(l, s, n, r, x, y) 333struct layer *l; 334char *s; 335int n; 336struct mchar *r; 337int x, y; 338{ 339 struct canvas *cv; 340 struct viewport *vp; 341 char *s2; 342 int xs2, xe2, y2; 343 344 if (x + n > l->l_width) 345 n = l->l_width - x; 346#ifdef HAVE_BRAILLE 347 if (bd.bd_refreshing) 348 { 349 BPutStr(l, s, n, r, x, y); 350 return; 351 } 352#endif 353 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 354 for (vp = cv->c_vplist; vp; vp = vp->v_next) 355 { 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)) 375 { 376 struct mchar mc; 377 mc = *r; 378 while (xs2 <= xe2) 379 { 380 mc.image = *s2++; 381 PutChar(RECODE_MCHAR(&mc), xs2++, y2); 382 } 383 continue; 384 } 385#endif 386 while (xs2++ <= xe2) 387 PUTCHARLP(*s2++); 388 } 389} 390 391void 392LPutWinMsg(l, s, n, r, x, y) 393struct layer *l; 394char *s; 395int n; 396struct mchar *r; 397int x, y; 398{ 399 struct canvas *cv; 400 struct viewport *vp; 401 char *s2; 402 int xs2, xe2, y2, len, len2; 403 struct mchar or; 404 405 if (x + n > l->l_width) 406 n = l->l_width - x; 407#ifdef HAVE_BRAILLE 408 if (bd.bd_refreshing) 409 { 410 BPutStr(l, s, n, r, x, y); 411 return; 412 } 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) 419 { 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 if (!PutWinMsg(s, xs2 - x - vp->v_xoff, len2)) 440 { 441 s2 = s + xs2 - x - vp->v_xoff; 442 while (len2-- > 0) 443 { 444 PUTCHARLP(*s2++); 445 xs2++; 446 } 447 } 448 else 449 xs2 = x + vp->v_xoff + len2; 450 if (xs2 < vp->v_xs) 451 xs2 = vp->v_xs; 452 or = D_rend; 453 GotoPos(xs2, y2); 454 SetRendition(&or); 455 while (xs2++ <= xe2) 456 PUTCHARLP(' '); 457 } 458} 459 460void 461LClearLine(l, y, xs, xe, bce, ol) 462struct layer *l; 463#ifdef __APPLE__ 464int y; 465#endif 466int xs, xe, bce; 467struct mline *ol; 468{ 469 struct canvas *cv; 470 struct viewport *vp; 471 int y2, xs2, xe2; 472 473 /* check for magic margin condition */ 474 if (xs >= l->l_width) 475 xs = l->l_width - 1; 476 if (xe >= l->l_width) 477 xe = l->l_width - 1; 478 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 479 for (vp = cv->c_vplist; vp; vp = vp->v_next) 480 { 481 xs2 = xs + vp->v_xoff; 482 xe2 = xe + vp->v_xoff; 483 y2 = y + vp->v_yoff; 484 if (y2 < vp->v_ys || y2 > vp->v_ye) 485 continue; 486 if (xs2 < vp->v_xs) 487 xs2 = vp->v_xs; 488 if (xe2 > vp->v_xe) 489 xe2 = vp->v_xe; 490 if (xs2 > xe2) 491 continue; 492 display = cv->c_display; 493 if (D_blocked) 494 continue; 495 ClearLine(ol ? mloff(RECODE_MLINE(ol), -vp->v_xoff) : (struct mline *)0, y2, xs2, xe2, bce); 496 } 497} 498 499void 500LClearArea(l, xs, ys, xe, ye, bce, uself) 501struct layer *l; 502int xs, ys, xe, ye; 503int bce; 504int uself; 505{ 506 struct canvas *cv; 507 struct viewport *vp; 508 int xs2, ys2, xe2, ye2; 509#ifdef HAVE_BRAILLE 510 if (bd.bd_refreshing) 511 return; 512#endif 513 /* check for magic margin condition */ 514 if (xs >= l->l_width) 515 xs = l->l_width - 1; 516 if (xe >= l->l_width) 517 xe = l->l_width - 1; 518 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 519 { 520 display = cv->c_display; 521 if (D_blocked) 522 continue; 523 for (vp = cv->c_vplist; vp; vp = vp->v_next) 524 { 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 if (xs2 < vp->v_xs) 530 xs2 = vp->v_xs; 531 if (xe2 > vp->v_xe) 532 xe2 = vp->v_xe; 533 if (xs2 > vp->v_xe) 534 ys2++; 535 if (xe2 < vp->v_xs) 536 ye2--; 537 if (ys2 < vp->v_ys) 538 ys2 = vp->v_ys; 539 if (ye2 > vp->v_ye) 540 ye2 = vp->v_ye; 541 if (ys2 > ye2) 542 continue; 543#if 0 544 xcs = vp->v_xoff; 545 xce = l->l_width - 1 + vp->v_xoff; 546 if (xcs < vp->v_xs) 547 xcs = vp->v_xs; 548 if (xce > vp->v_xe) 549 xce = vp->v_xe; 550 if (xcs > xce) 551 continue; 552 if (ys2 != ys + vp->v_yoff) 553 xs2 = xcs; 554 if (ye2 != ye + vp->v_yoff) 555 xe2 = xce; 556 display = cv->c_display; 557 ClearArea(xs2, ys2, xcs, xce, xe2, ye2, bce, uself); 558#else 559 if (xs == 0 || ys2 != ys + vp->v_yoff) 560 xs2 = vp->v_xs; 561 if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff) 562 xe2 = vp->v_xe; 563 display = cv->c_display; 564 ClearArea(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, bce, uself); 565#endif 566 } 567 } 568} 569 570void 571LCDisplayLine(l, ml, y, xs, xe, isblank) 572struct layer *l; 573struct mline *ml; 574int y, xs, xe; 575int isblank; 576{ 577 struct canvas *cv; 578 struct viewport *vp; 579 int xs2, xe2, y2; 580#ifdef HAVE_BRAILLE 581 if (bd.bd_refreshing) 582 { 583 BCDisplayLine(l, ml, y, xs, xe, isblank); 584 return; 585 } 586#endif 587 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 588 { 589 display = cv->c_display; 590 if (D_blocked) 591 continue; 592 for (vp = cv->c_vplist; vp; vp = vp->v_next) 593 { 594 xs2 = xs + vp->v_xoff; 595 xe2 = xe + vp->v_xoff; 596 y2 = y + vp->v_yoff; 597 if (y2 < vp->v_ys || y2 > vp->v_ye) 598 continue; 599 if (xs2 < vp->v_xs) 600 xs2 = vp->v_xs; 601 if (xe2 > vp->v_xe) 602 xe2 = vp->v_xe; 603 if (xs2 > xe2) 604 continue; 605 display = cv->c_display; 606 debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2); 607 debug1(" mloff = %d\n", -vp->v_xoff); 608 DisplayLine(isblank ? &mline_blank : &mline_null, mloff(RECODE_MLINE(ml), -vp->v_xoff), y2, xs2, xe2); 609 } 610 } 611} 612 613void 614LCDisplayLineWrap(l, ml, y, from, to, isblank) 615struct layer *l; 616struct mline *ml; 617int y, from, to; 618int isblank; 619{ 620 struct mchar nc; 621 copy_mline2mchar(&nc, ml, 0); 622#ifdef DW_CHARS 623 if (dw_left(ml, 0, l->l_encoding)) 624 { 625 nc.mbcs = ml->image[1]; 626 from++; 627 } 628#endif 629 LWrapChar(l, &nc, y - 1, -1, -1, 0); 630 from++; 631 if (from <= to) 632 LCDisplayLine(l, ml, y, from, to, isblank); 633} 634 635void 636LSetRendition(l, r) 637struct layer *l; 638struct mchar *r; 639{ 640 struct canvas *cv; 641 642 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 643 { 644 display = cv->c_display; 645 if (D_blocked) 646 continue; 647 SetRendition(r); 648 } 649} 650 651void 652LWrapChar(l, c, y, top, bot, ins) 653struct layer *l; 654struct mchar *c; 655int y, top, bot; 656int ins; 657{ 658 struct canvas *cv, *cvlist, *cvlnext; 659 struct viewport *vp, *evp, **vpp; 660 int yy, y2, yy2, top2, bot2; 661 int bce; 662 663#ifdef COLOR 664 bce = rend_getbg(c); 665#else 666 bce = 0; 667#endif 668 if (y != bot) 669 { 670 /* simple case: no scrolling */ 671 672 /* cursor after wrapping */ 673 yy = y == l->l_height - 1 ? y : y + 1; 674 675 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 676 { 677 y2 = 0; /* gcc -Wall */ 678 display = cv->c_display; 679 if (D_blocked) 680 continue; 681 /* find the viewport of the wrapped character */ 682 for (vp = cv->c_vplist; vp; vp = vp->v_next) 683 { 684 y2 = y + vp->v_yoff; 685 yy2 = yy + vp->v_yoff; 686 if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe) 687 break; 688 } 689 if (vp == 0) 690 continue; /* nothing to do, character not visible */ 691 /* find the viewport of the character at the end of the line*/ 692 for (evp = cv->c_vplist; evp; evp = evp->v_next) 693 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) 694 break; /* gotcha! */ 695 if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye)) 696 { 697 /* no wrapping possible */ 698 debug("LWrap: can't wrap!\n"); 699 cvlist = l->l_cvlist; 700 cvlnext = cv->c_lnext; 701 l->l_cvlist = cv; 702 cv->c_lnext = 0; 703 if (ins) 704 LInsChar(l, c, 0, yy, 0); 705 else 706 LPutChar(l, c, 0, yy); 707 l->l_cvlist = cvlist; 708 cv->c_lnext = cvlnext; 709 } 710 else 711 { 712 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins); 713 } 714 } 715 } 716 else 717 { 718 /* hard case: scroll up*/ 719 720 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 721 { 722 display = cv->c_display; 723 if (D_blocked) 724 continue; 725 /* search for wrap viewport */ 726 for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next) 727 { 728 yy2 = bot + vp->v_yoff; 729 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) 730 break; 731 } 732 733 if (vp) 734 { 735 /* great, can use Wrap on the vp */ 736 /* temporarily remove vp from cvlist */ 737 *vpp = vp->v_next; 738 } 739 if (cv->c_vplist) 740 { 741 /* scroll all viewports != vp */ 742 cvlist = l->l_cvlist; 743 cvlnext = cv->c_lnext; 744 l->l_cvlist = cv; 745 cv->c_lnext = 0; 746 LScrollV(l, 1, top, bot, bce); 747 if (!vp) 748 { 749 if (ins) 750 LInsChar(l, c, 0, bot, 0); 751 else 752 LPutChar(l, c, 0, bot); 753 } 754 l->l_cvlist = cvlist; 755 cv->c_lnext = cvlnext; 756 } 757 if (vp) 758 { 759 /* add vp back to cvlist */ 760 *vpp = vp; 761 top2 = top + vp->v_yoff; 762 bot2 = bot + vp->v_yoff; 763 if (top2 < vp->v_ys) 764 top2 = vp->v_ys; 765 WrapChar(RECODE_MCHAR(c), vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins); 766 } 767 } 768 } 769} 770 771 772void 773LCursorVisibility(l, vis) 774struct layer *l; 775int vis; 776{ 777 struct canvas *cv; 778 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 779 { 780 display = cv->c_display; 781 if (D_blocked) 782 continue; 783 if (cv != D_forecv) 784 continue; 785 CursorVisibility(vis); 786 } 787} 788 789void 790LSetFlow(l, flow) 791struct layer *l; 792int flow; 793{ 794 struct canvas *cv; 795 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 796 { 797 display = cv->c_display; 798 if (cv != D_forecv) 799 continue; 800 SetFlow(flow); 801 } 802} 803 804void 805LKeypadMode(l, on) 806struct layer *l; 807int on; 808{ 809 struct canvas *cv; 810 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 811 { 812 display = cv->c_display; 813 if (D_blocked) 814 continue; 815 if (cv != D_forecv) 816 continue; 817 KeypadMode(on); 818 } 819} 820 821void 822LCursorkeysMode(l, on) 823struct layer *l; 824int on; 825{ 826 struct canvas *cv; 827 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 828 { 829 display = cv->c_display; 830 if (D_blocked) 831 continue; 832 if (cv != D_forecv) 833 continue; 834 CursorkeysMode(on); 835 } 836} 837 838void 839LMouseMode(l, on) 840struct layer *l; 841int on; 842{ 843 struct canvas *cv; 844 for (cv = l->l_cvlist; cv; cv = cv->c_lnext) 845 { 846 display = cv->c_display; 847 if (D_blocked) 848 continue; 849 if (cv != D_forecv) 850 continue; 851 MouseMode(on); 852 } 853} 854 855 856/*******************************************************************/ 857 858void 859LClearAll(l, uself) 860struct layer *l; 861int uself; 862{ 863 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, uself); 864} 865 866void 867LRefreshAll(l, isblank) 868struct layer *l; 869int isblank; 870{ 871 struct layer *oldflayer; 872 int y; 873 874 debug1("LRefreshAll isblank=%d\n", isblank); 875 oldflayer = flayer; 876 flayer = l; 877 if (!isblank) 878 LClearArea(l, 0, 0, l->l_width - 1, l->l_height - 1, 0, 0); 879 /* signal full refresh */ 880 LayRedisplayLine(-1, -1, -1, 1); 881 for (y = 0; y < l->l_height; y++) 882 LayRedisplayLine(y, 0, l->l_width - 1, 1); 883 flayer = oldflayer; 884} 885 886 887void 888KillLayerChain(lay) 889struct layer *lay; 890{ 891 struct canvas *cv, *ncv; 892 struct layer *l, *oldflayer; 893 894 oldflayer = flayer; 895 debug1("KillLayerChain %#x\n", lay); 896 for (l = lay; l; l = l->l_next) 897 { 898 if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf) 899 break; 900 debug1("- killing %#x\n", l); 901 if (oldflayer == l) 902 oldflayer = 0; 903 for (cv = l->l_cvlist; cv; cv = ncv) 904 { 905 ncv = cv->c_lnext; 906 cv->c_layer = 0; 907 cv->c_lnext = 0; 908 } 909 } 910 flayer = lay; 911 while (flayer != l) 912 ExitOverlayPage(); 913 flayer = oldflayer; 914} 915 916 917/*******************************************************************/ 918/*******************************************************************/ 919 920/* 921 * Layer creation / removal 922 */ 923 924int 925InitOverlayPage(datasize, lf, block) 926int datasize; 927struct LayFuncs *lf; 928int block; 929{ 930 char *data; 931 struct layer *newlay; 932 struct canvas *cv, *cvp, **cvpp; 933 struct win *p; 934 935 ASSERT(flayer); 936 937 cv = 0; 938 if (display && D_forecv->c_layer == flayer) 939 cv = D_forecv; /* work only on this cv! */ 940 941 if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0) 942 { 943 Msg(0, "No memory for layer struct"); 944 return -1; 945 } 946 debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay); 947 data = 0; 948 if (datasize) 949 { 950 if ((data = malloc(datasize)) == 0) 951 { 952 free((char *)newlay); 953 Msg(0, "No memory for layer data"); 954 return -1; 955 } 956 bzero(data, datasize); 957 } 958 959 p = Layer2Window(flayer); 960 961 if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0))) 962 { 963 if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0) 964 KillLayerChain(p->w_savelayer); 965 p->w_savelayer = newlay; 966 } 967 968 if (cv && flayer->l_next == 0 && !block) 969 { 970 struct display *olddisplay = display; 971 display = cv->c_display; 972 RemoveStatus(); 973 display = olddisplay; 974 975 /* new branch -> just get canvas vps */ 976 for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext) 977 if (cvp == cv) 978 break; 979 ASSERT(cvp); 980 *cvpp = cv->c_lnext; 981 newlay->l_cvlist = cv; 982 cv->c_lnext = 0; 983 cv->c_layer = newlay; 984 } 985 else 986 { 987 LAY_DISPLAYS(flayer, RemoveStatus()); 988 if (block) 989 debug("layer is blocking\n"); 990 if (block && flayer->l_layfn == &WinLf) 991 { 992 debug("...and is first, so window gets blocked\n"); 993 ASSERT(p->w_blocked == 0); 994 p->w_blocked++; 995 newlay->l_blocking = 1; 996 } 997 /* change all canvases */ 998 newlay->l_cvlist = flayer->l_cvlist; 999 for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext) 1000 cvp->c_layer = newlay; 1001 flayer->l_cvlist = 0; 1002 } 1003 newlay->l_width = flayer->l_width; 1004 newlay->l_height = flayer->l_height; 1005 newlay->l_encoding = 0; 1006 newlay->l_layfn = lf; 1007 newlay->l_data = data; 1008 newlay->l_next = flayer; 1009 newlay->l_bottom = flayer->l_bottom; 1010 flayer = newlay; 1011 LayRestore(); 1012 return 0; 1013} 1014 1015void 1016ExitOverlayPage() 1017{ 1018 struct layer *oldlay; 1019 struct win *p; 1020 int doredisplay = 0; 1021 struct canvas *cv, *ocv; 1022 1023 ASSERT(flayer); 1024 debug1("Exiting layer %#x\n", (unsigned int)flayer); 1025 oldlay = flayer; 1026 if (oldlay->l_data) 1027 free(oldlay->l_data); 1028 1029 p = Layer2Window(flayer); 1030 1031 flayer = oldlay->l_next; 1032 if (flayer->l_layfn == &WinLf) 1033 { 1034 if (oldlay->l_blocking) 1035 { 1036 ASSERT(p->w_blocked > 0); 1037 p->w_blocked--; 1038 debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked); 1039 } 1040 /* don't warp dead layers: check cvlist */ 1041 if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist) 1042 { 1043 debug("warping to top of blocking chain!\n"); 1044 /* warp ourself into savelayer */ 1045 flayer = p->w_savelayer; 1046 doredisplay = 1; 1047 } 1048 } 1049 if (p && p->w_savelayer == oldlay) 1050 p->w_savelayer = flayer; 1051#ifdef COPY_PASTE 1052 if (p && oldlay == p->w_paster.pa_pastelayer) 1053 p->w_paster.pa_pastelayer = 0; 1054#endif 1055 1056 /* add all canvases back into next layer's canvas list */ 1057 for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext) 1058 { 1059 cv->c_layer = flayer; 1060 ocv = cv; 1061 } 1062 if (ocv) 1063 { 1064 cv = flayer->l_cvlist; 1065 ocv->c_lnext = 0; 1066 flayer->l_cvlist = oldlay->l_cvlist; 1067 /* redisplay only the warped cvs */ 1068 if (doredisplay) 1069 LRefreshAll(flayer, 0); 1070 ocv->c_lnext = cv; 1071 } 1072 oldlay->l_cvlist = 0; 1073 free((char *)oldlay); 1074 LayRestore(); 1075 LaySetCursor(); 1076} 1077 1078void 1079/*VARARGS2*/ 1080#if defined(USEVARARGS) && defined(__STDC__) 1081LMsg(int err, char *fmt, VA_DOTS) 1082#else 1083LMsg(err, fmt, VA_DOTS) 1084int err; 1085char *fmt; 1086VA_DECL 1087#endif 1088{ 1089 VA_LIST(ap) 1090 char buf[MAXPATHLEN*2]; 1091 char *p = buf; 1092 struct canvas *cv; 1093 1094 VA_START(ap, fmt); 1095 fmt = DoNLS(fmt); 1096 (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); 1097 VA_END(ap); 1098 if (err) 1099 { 1100 p += strlen(p); 1101 *p++ = ':'; 1102 *p++ = ' '; 1103 strncpy(p, strerror(err), buf + sizeof(buf) - p - 1); 1104 buf[sizeof(buf) - 1] = 0; 1105 } 1106 debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer); 1107 for (display = displays; display; display = display->d_next) 1108 { 1109 for (cv = D_cvlist; cv; cv = cv->c_next) 1110 if (cv->c_layer == flayer) 1111 break; 1112 if (cv == 0) 1113 continue; 1114 MakeStatus(buf); 1115 } 1116} 1117 1118