1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 /*LINTLIBRARY*/ 41 42 #include <sys/types.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include "curses_inc.h" 46 47 /* 48 * Make the screen look like "win" over the area covered by win. 49 * This routine may use insert/delete char/line and scrolling-region. 50 * win : the window being updated 51 */ 52 53 extern int outchcount; 54 55 static void _updateln(int), _turn_off_background(void), 56 _setmark1(int, int, chtype *), 57 _setmark2(int, int, chtype *), _rmargin(int), 58 _useceod(int, int); 59 static int _useidch(chtype *, chtype *, int, int, int *), 60 _prefix(chtype *, chtype *, int, int, int *), 61 _getceod(int, int); 62 63 static short cy, cx, /* current cursor coord */ 64 scrli, /* actual screen lines */ 65 scrco; /* actual screen columns */ 66 static char **marks; /* the mark table for cookie terminals */ 67 static char **color_marks; /* color mark table for cookie terminals */ 68 69 #define _ISMARK1(y, x) (marks[y][x / BITSPERBYTE] & (1 << (x % BITSPERBYTE))) 70 #define _ISMARK2(y, x) (color_marks ? (color_marks[y][x / BITSPERBYTE] & \ 71 (1 << (x % BITSPERBYTE))) : FALSE) 72 73 #define _VIDEO(c) ((c) & A_ATTRIBUTES & ~A_COLOR) 74 #define _COLOR(c) ((c) & A_COLOR) 75 76 #ifdef _VR2_COMPAT_CODE 77 extern char _endwin; 78 #endif /* _VR2_COMPAT_CODE */ 79 80 int 81 wrefresh(WINDOW *win) 82 { 83 84 short *bnsch, *ensch; 85 SLK_MAP *slk; 86 int wx, wy, nc, boty, clby, idby, *hs, curwin; 87 88 curwin = (win == curscr); 89 90 /* don't allow curscr refresh if the screen was just created */ 91 92 if (curwin && curscr->_sync) 93 return (OK); 94 95 /* go thru _stdbody */ 96 if (!curwin && (win != _virtscr)) 97 (void) wnoutrefresh(win); 98 99 /* if there is typeahead */ 100 if ((_INPUTPENDING = _chkinput()) == TRUE) { 101 if (curwin) 102 curscr->_clear = TRUE; 103 return (OK); 104 } 105 106 if (curwin || curscr->_clear) 107 _virtscr->_clear = TRUE; 108 109 /* save curscr cursor coordinates */ 110 cy = curscr->_cury; 111 cx = curscr->_curx; 112 113 /* to simplify code in some cases */ 114 marks = _MARKS; 115 color_marks = _COLOR_MARKS; 116 scrli = curscr->_maxy; 117 scrco = curscr->_maxx; 118 slk = SP->slk; 119 120 outchcount = 0; 121 122 /* make sure we're in program mode */ 123 if (SP->fl_endwin) { 124 /* If endwin is equal to 2 it means we just did a newscreen. */ 125 if (SP->fl_endwin == TRUE) { 126 (void) reset_prog_mode(); 127 if (SP->kp_state) 128 (void) tputs(keypad_xmit, 1, _outch); 129 if (slk) 130 (*_do_slk_tch)(); 131 if (SP->fl_meta) 132 (void) tputs(meta_on, 1, _outch); 133 if (cur_term->_cursorstate != 1) 134 _PUTS(cur_term->cursor_seq[cur_term-> 135 _cursorstate], 0); 136 } 137 _PUTS(enter_ca_mode, 1); 138 (void) tputs(ena_acs, 1, _outch); 139 140 if (exit_attribute_mode) 141 _PUTS(tparm_p0(exit_attribute_mode), 1); 142 else 143 /* 144 * If there is no exit_attribute mode, then vidupdate 145 * could only possibly turn off one of the below three 146 * so that's all we ask it turn off. 147 */ 148 vidupdate(A_NORMAL, (A_ALTCHARSET | A_STANDOUT | 149 A_UNDERLINE), _outch); 150 151 SP->fl_endwin = FALSE; 152 153 #ifdef _VR2_COMPAT_CODE 154 _endwin = (char)FALSE; 155 #endif /* _VR2_COMPAT_CODE */ 156 } 157 158 /* clear the screen if required */ 159 if (_virtscr->_clear) { 160 /* SS: colors */ 161 if (back_color_erase) 162 _turn_off_background(); 163 164 _PUTS(clear_screen, scrli); 165 cy = cx = curscr->_curx = curscr->_cury = 0; 166 167 /* _sync indicates that this a new screen */ 168 if (!curscr->_sync) 169 (void) werase(curscr); 170 else { 171 nc = scrco / BITSPERBYTE - (scrco % 172 BITSPERBYTE ? 0 : 1); 173 wy = scrli - 1; 174 bnsch = _BEGNS; ensch = _ENDNS; 175 hs = _CURHASH; 176 for (; wy >= 0; --wy) { 177 *bnsch++ = scrco; 178 *ensch++ = -1; 179 *hs++ = 0; 180 if (marks) 181 for (wx = nc; wx >= 0; --wx) 182 marks[wy][wx] = 0; 183 } 184 } 185 186 _virtscr->_clear = curscr->_sync = curscr->_clear = FALSE; 187 if (slk) 188 (*_do_slk_tch)(); 189 190 /* pretend _virtscr has been totally changed */ 191 (void) wtouchln(_virtscr, 0, scrli, -1); 192 _VIRTTOP = 0; 193 _VIRTBOT = scrli - 1; 194 195 /* will not do clear-eod or ins/del lines */ 196 clby = idby = scrli; 197 } else 198 clby = idby = -1; 199 200 /* Software soft labels; if _changed == 2, slk's are in clear mode. */ 201 if (slk && slk->_win && (slk->_changed == TRUE)) 202 (*_do_slk_noref)(); 203 204 /* do line updating */ 205 _virtscr->_clear = FALSE; 206 wy = _VIRTTOP; 207 boty = _VIRTBOT + 1; 208 bnsch = _virtscr->_firstch + wy; 209 ensch = _virtscr->_lastch + wy; 210 211 for (; wy < boty; ++wy, ++bnsch, ++ensch) { 212 /* this line is up-to-date */ 213 if (*bnsch >= scrco) 214 goto next; 215 216 /* there is type-ahead */ 217 if (!curwin && (_INPUTPENDING = _chkinput()) == TRUE) { 218 /* LINTED */ 219 _VIRTTOP = (short)wy; 220 goto done; 221 } 222 223 if (clby < 0) { 224 /* now we have to work, check for ceod */ 225 clby = _getceod(wy, boty); 226 227 /* check for insert/delete lines */ 228 if (_virtscr->_use_idl) 229 idby = (*_setidln)(); 230 } 231 232 /* try clear-to-eod */ 233 if (wy == clby) 234 _useceod(wy, boty); 235 236 /* try ins/del lines */ 237 if (wy == idby) { 238 curscr->_cury = cy; 239 curscr->_curx = cx; 240 (*_useidln)(); 241 cy = curscr->_cury; 242 cx = curscr->_curx; 243 } 244 245 if (*bnsch < scrco) 246 _updateln(wy); 247 248 next: 249 *bnsch = _INFINITY; 250 *ensch = -1; 251 } 252 253 /* do hardware soft labels; if _changed == 2, */ 254 /* slk's are in clear mode. */ 255 if (slk && (slk->_changed == TRUE) && !(slk->_win)) 256 (*_do_slk_ref)(); 257 258 /* move cursor */ 259 wy = _virtscr->_cury; 260 wx = _virtscr->_curx; 261 if (wy != cy || wx != cx) { 262 (void) mvcur(cy, cx, wy, wx); 263 /* LINTED */ 264 cy = (short)wy; 265 /* LINTED */ 266 cx = (short)wx; 267 } 268 269 /* reset the flags */ 270 curscr->_clear = FALSE; 271 _virtscr->_use_idl = FALSE; 272 _virtscr->_use_idc = TRUE; 273 _INPUTPENDING = FALSE; 274 275 /* virtual image is now up-to-date */ 276 _VIRTTOP = scrli; 277 _VIRTBOT = -1; 278 279 done : 280 curscr->_cury = cy; 281 curscr->_curx = cx; 282 (void) fflush(SP->term_file); 283 return (outchcount); 284 } 285 286 /* Shift appropriate portions of a line to leave space for cookies. */ 287 288 static chtype * 289 _shove(int wy) 290 { 291 chtype *wcp, *cp, prev; 292 short curx; 293 int x, cury, didshift; 294 static chtype *line; 295 static int length; 296 297 /* allocate space for shifted line */ 298 if (length < scrco) { 299 free(line); 300 line = (chtype *) malloc(scrco * sizeof (chtype)); 301 length = line ? scrco : 0; 302 } 303 304 /* no space to do it */ 305 if (!line) 306 return (_virtscr->_y[wy]); 307 308 prev = A_NORMAL; 309 cp = line; 310 wcp = _virtscr->_y[wy]; 311 curx = _virtscr->_curx; 312 cury = _virtscr->_cury; 313 didshift = FALSE; 314 315 for (x = 0; x < scrco; ++x, ++wcp, ++cp) { 316 if (_ATTR(*wcp) != prev) { 317 /* use existing blank */ 318 if (_CHAR(*wcp) == ' ') 319 *cp = ' ' | _ATTR(*(wcp + 1)); 320 /* use previous blank */ 321 else 322 if ((x > 0) && _CHAR(*(cp - 1)) == ' ') { 323 *(cp - 1) = ' ' | _ATTR(*wcp); 324 *cp = *wcp; 325 } else { 326 if ((curx >= x) && (cury == wy)) 327 ++curx; 328 *cp = ' ' | _ATTR(*wcp); 329 --wcp; 330 didshift = TRUE; 331 } 332 prev = _ATTR(*cp); 333 } else 334 *cp = *wcp; 335 } 336 337 /* make sure that the end of the line is normal */ 338 cp = line + scrco - 1; 339 if (didshift || (_ATTR(*cp) != A_NORMAL) || 340 ((wy == scrli - 1) && (_ATTR(*(cp - 1)) != A_NORMAL))) { 341 *cp = didshift ? ' ' : _CHAR(*cp); 342 if (wy == scrli - 1) 343 *(cp - 1) = didshift ? ' ' : _CHAR(*(cp - 1)); 344 } 345 346 if (wy == cury) 347 _virtscr->_curx = curx >= scrco ? scrco - 1 : curx; 348 349 return (line); 350 } 351 352 /* 353 * Update a line. 354 * Three schemes of coloring are allowed. The first is the usual 355 * pen-up/pen-down model. The second is the HP26*-like model. 356 * In this case, colorings are specified by intervals, the left 357 * side of the interval has the coloring mark, the right side 358 * has the end-coloring mark. We assume that clear sequences will 359 * clear ALL marks in the affected regions. The second case is 360 * signified by the boolean flag ceol_standout_glitch. 361 * The third case is for terminals that leave visible cookies on 362 * the screen. This last case is at most an approximation of what 363 * can be done right. 364 */ 365 366 static void 367 _updateln(int wy) 368 { 369 chtype *wcp, *scp, *wp, *sp, wc, sc; 370 int wx, lastx, x, mtch, idch, blnkx, idcx, video_attrx, 371 color_attrx, maxi, endns, begns, wx_sav, multi_col; 372 bool redraw, changed, didcolor, didvideo; 373 374 redraw = (_virtscr->_firstch[wy] == _REDRAW); 375 endns = _ENDNS[wy]; 376 begns = _BEGNS[wy]; 377 378 /* easy case */ 379 if (!redraw && (_virtscr->_lastch[wy] == _BLANK) && (begns >= scrco)) 380 return; 381 382 /* line images */ 383 wcp = magic_cookie_glitch <= 0 ? _virtscr->_y[wy] : _shove(wy); 384 scp = curscr->_y[wy]; 385 386 /* the interval to be updated */ 387 if (redraw || magic_cookie_glitch >= 0) { 388 wx = 0; 389 lastx = scrco; 390 } else { 391 wx = _virtscr->_firstch[wy]; 392 lastx = _virtscr->_lastch[wy] == _BLANK ? scrco : 393 _virtscr->_lastch[wy] + 1; 394 } 395 396 /* skip equal parts */ 397 if (!redraw) { 398 /* skip the starting equal part */ 399 wp = wcp + wx; 400 sp = scp + wx; 401 for (; wx < lastx; ++wx) 402 if (*wp++ != *sp++) 403 break; 404 if (wx >= lastx) 405 return; 406 407 /* start update at an entire character */ 408 for (sp = scp+wx, wp = wcp+wx; wp > wcp; --wp, --sp, --wx) 409 if (!ISCBIT(*wp) && !ISCBIT(*sp)) 410 break; 411 412 /* skip the ending equal part */ 413 wp = wcp + lastx - 1; 414 sp = scp + lastx - 1; 415 for (; lastx > wx; --lastx) 416 if (*wp-- != *sp--) 417 break; 418 ++wp; 419 ++wp; 420 ++sp; 421 ++sp; 422 for (; lastx < scrco; ++wp, ++sp, ++lastx) 423 if (!ISCBIT(*wp) && !ISCBIT(*sp)) 424 break; 425 } 426 427 /* place to do clear-eol */ 428 if (!clr_eol || endns >= lastx) 429 blnkx = scrco; 430 else 431 if (_virtscr->_lastch[wy] == _BLANK) 432 blnkx = -1; 433 else { 434 for (blnkx = lastx - 1, wp = wcp + blnkx; 435 blnkx >= wx; --blnkx, --wp) 436 if (_DARKCHAR(*wp)) 437 break; 438 for (sp = scp + blnkx + 1; blnkx < scrco - 1; 439 ++sp, ++blnkx) 440 if (!ISCBIT(*sp)) 441 break; 442 if (blnkx + _COST(Clr_eol) >= lastx) 443 blnkx = scrco; 444 } 445 446 /* on cookie terminals, we may need to do more work */ 447 if (marks) { 448 /* video_attrx = color_attrx = scrco; */ 449 video_attrx = color_attrx = (lastx >= scrco) ? lastx - 1 : 450 lastx; 451 452 /* find the last video attribute on the line */ 453 454 wp = wcp + video_attrx; 455 for (; video_attrx >= wx; --video_attrx, --wp) 456 if (_VIDEO(*wp) != A_NORMAL) 457 break; 458 459 /* find the last color attribute on the line */ 460 461 if (color_marks) { 462 wp = wcp + color_attrx; 463 for (; color_attrx >= wx; --color_attrx, --wp) 464 if (_COLOR(*wp) != A_NORMAL) 465 break; 466 if (color_attrx < lastx) 467 color_attrx++; 468 } 469 if (video_attrx < lastx) 470 video_attrx++; 471 472 if (video_attrx >= scrco) 473 --video_attrx; 474 if (color_marks && color_attrx >= scrco) 475 --color_attrx; 476 if (magic_cookie_glitch > 0 && wy == scrli - 1 && 477 video_attrx == scrco - 1) 478 --video_attrx; 479 if (color_marks && magic_cookie_glitch > 0 && 480 wy == scrli - 1 && color_attrx == scrco - 1) 481 --color_attrx; 482 for (wp = wcp+video_attrx; wp >= wcp+wx; --wp) 483 if (!ISCBIT(*wp)) 484 break; 485 } 486 487 /* place for insert/delete chars */ 488 #define SLACK 4 489 if (redraw || (!SP->dchok && !SP->ichok) || !(_virtscr->_use_idc) || 490 endns < wx || (endns >= lastx && (scrco - lastx) > SLACK)) { 491 idcx = scrco; 492 } else 493 if (!marks) 494 idcx = -1; 495 else { 496 /* on cookie term, only do idch where no attrs */ 497 /* are used */ 498 for (idcx = scrco - 1, wp = wcp + idcx; idcx >= wx; 499 --idcx, --wp) 500 if (_ATTR(*wp) || _ISMARK1(wy, idcx) || 501 _ISMARK2(wy, idcx)) 502 break; 503 if (idcx >= scrco - SLACK) 504 idcx = scrco; 505 } 506 507 if (idcx < lastx && endns >= lastx) 508 lastx = scrco; 509 510 /* max amount of insert allow */ 511 if (idcx == scrco || !SP->ichok) 512 maxi = 0; 513 else 514 if (lastx == scrco) 515 maxi = scrco; 516 else 517 maxi = lastx - (endns + 1); 518 519 /* go */ 520 wcp += wx; 521 scp += wx; 522 didvideo = changed = FALSE; 523 didcolor = (color_marks) ? FALSE : TRUE; 524 525 while (wx < lastx) { 526 /* skip things that are already right */ 527 if (!redraw) { 528 multi_col = 0; 529 wx_sav = wx; 530 for (; wx < lastx; ++wx, ++wcp, ++scp) 531 if (*wcp != *scp) 532 break; 533 if (wx >= lastx) 534 goto done; 535 for (; wx > wx_sav; --wx, --wcp, --scp) { 536 if (!ISCBIT(*wcp) && !ISCBIT(*scp)) 537 break; 538 multi_col = 1; 539 } 540 } 541 542 /* try clear-bol, we'll assume exclusive clr_bol */ 543 if (!changed && !marks && clr_bol && blnkx > wx && 544 begns >= wx) { 545 for (x = wx, wp = wcp; x < lastx; ++x, ++wp) 546 if (_DARKCHAR(*wp)) 547 break; 548 /* clearing only whole screen characters */ 549 for (sp = scp+(x-wx); x >= wx; --x, --sp) 550 if (!ISCBIT(*sp)) 551 break; 552 x -= 1; 553 554 if ((x - (redraw ? 0 : begns)) > _COST(Clr_bol)) { 555 (void) mvcur(cy, cx, wy, x); 556 /* MORE?: colors - mvcur will shuts of */ 557 /* colors when msgr is not defined */ 558 559 /* SS: colors */ 560 if (back_color_erase) 561 _turn_off_background(); 562 563 _PUTS(clr_bol, 1); 564 /* LINTED */ 565 cy = (short)wy; 566 /* LINTED */ 567 cx = (short)x; 568 569 mtch = x - wx; 570 (void) memcpy(scp, wcp, 571 (mtch * sizeof (chtype))); 572 wcp += mtch; 573 scp += mtch; 574 wx = x; 575 } 576 } 577 578 /* screen image is changing */ 579 changed = TRUE; 580 581 /* move to the point to start refresh */ 582 if (cy != wy || cx != wx) 583 (void) mvcur(cy, cx, wy, wx); 584 /* LINTED */ 585 cy = (short)wy; 586 /* LINTED */ 587 cx = (short)wx; 588 589 /* update screen image */ 590 while (wx < lastx) { 591 wc = *wcp; 592 sc = *scp; 593 594 if (!redraw && !multi_col && wc == sc) 595 break; 596 597 /* real video attributes */ 598 if (marks) 599 curscr->_attrs = _ATTR(sc); 600 601 /* blanks only */ 602 if (wx > blnkx) { 603 /* SS: colors */ 604 if (back_color_erase) 605 _turn_off_background(); 606 607 _PUTS(clr_eol, 1); 608 /* LINTED */ 609 curscr->_curx = (short)wx; 610 /* LINTED */ 611 curscr->_cury = (short)wy; 612 (void) wclrtoeol(curscr); 613 614 if (marks && wx > 0 && _ATTR(*(scp - 1)) != 615 A_NORMAL) { 616 _VIDS(A_NORMAL, _ATTR(*(scp - 1))); 617 if (_VIDEO(*scp - 1)) 618 _setmark1(wy, wx, NULL); 619 if (_COLOR(*scp - 1)) 620 _setmark2(wy, wx, NULL); 621 } 622 goto done; 623 } 624 625 /* try insert/delete chars */ 626 if (wx > idcx && !ISCBIT(*scp) && 627 (mtch = _useidch(wcp, scp, lastx - wx, 628 maxi, &idch))) { 629 maxi -= idch; 630 wx += mtch; 631 scp += mtch; 632 wcp += mtch; 633 break; 634 } 635 636 /* about to output chars, make sure insert */ 637 /* mode is off */ 638 if (SP->phys_irm) 639 _OFFINSERT(); 640 641 /* color and video attributes */ 642 if (_ATTR(wc) != curscr->_attrs) { 643 bool color_change = FALSE; 644 bool video_change = FALSE; 645 646 if (marks) { 647 if (_VIDEO(wc) != 648 _VIDEO(curscr->_attrs)) { 649 video_change = TRUE; 650 } 651 } 652 if (color_marks) { 653 if (_COLOR(wc) != 654 _COLOR(curscr->_attrs)) { 655 color_change = TRUE; 656 } 657 } 658 659 /* the following may occurs when, for */ 660 /* example the application */ 661 /* is written for color terminal and then */ 662 /* run on a monocrome */ 663 664 if (marks && !video_change && !color_change) 665 goto no_change; 666 667 /* prevent spilling out of line */ 668 if (marks && !(didcolor && didvideo)) { 669 if ((video_change && !_ISMARK1(wy, 670 video_attrx)) || (color_change && 671 !_ISMARK2(wy, color_attrx))) { 672 int tempx; 673 chtype sa = curscr->_attrs; 674 bool first = FALSE; 675 bool second = FALSE; 676 677 if (!didvideo && video_change && 678 !_ISMARK1(wy, video_attrx)) { 679 didvideo = TRUE; 680 (void) mvcur(wy, wx, 681 wy, video_attrx); 682 _VIDS(_VIDEO(_virtscr->_y[wy] 683 [video_attrx]), 684 _VIDEO(_virtscr->_y[wy] 685 [video_attrx-1])); 686 _setmark1(wy, video_attrx, 687 NULL); 688 first = TRUE; 689 } 690 691 if (!didcolor && color_change && 692 !_ISMARK2(wy, color_attrx)) { 693 didcolor = TRUE; 694 tempx = first ? video_attrx : wx; 695 if (tempx != color_attrx) 696 (void) mvcur(wy, tempx, wy, 697 color_attrx); 698 /* 699 * sc = _COLOR(curscr->_y[wy][color_attrx]); 700 * _VIDS(sc, (~sc & A_COLOR)); 701 */ 702 _VIDS(_COLOR(_virtscr->_y[wy] 703 [color_attrx]), 704 _COLOR(_virtscr->_y[wy] 705 [color_attrx-1])); 706 _setmark2(wy, color_attrx, NULL); 707 second = TRUE; 708 } 709 (void) mvcur(wy, (second ? color_attrx : 710 video_attrx), wy, wx); 711 curscr->_attrs = sa; 712 } 713 } 714 715 _VIDS(_ATTR(wc), curscr->_attrs); 716 717 /* on cookie terminals mark the interval */ 718 if (video_change) 719 _setmark1(wy, wx, scp); 720 if (color_change) 721 _setmark2(wy, wx, scp); 722 } 723 724 /* end-of-line */ 725 no_change: 726 x = 1; 727 if (_scrmax > 1) 728 x = _curs_scrwidth[TYPE(RBYTE(wc))]; 729 if (wx == scrco - x) { 730 _rmargin(wx); 731 goto done; 732 } 733 734 if (transparent_underline && erase_overstrike && 735 _CHAR(wc) == '_') { 736 (void) _outch(' '); 737 (void) mvcur(wy, wx + 1, wy, wx); 738 } 739 740 /* put out the character */ 741 (void) _outwch(tilde_glitch && _CHAR(wc) == '~' ? '`' : wc); 742 743 *scp++ = wc; 744 wcp++; 745 wx++; 746 cx++; 747 /* output entire multi-byte chars */ 748 while (wx < lastx && ISCBIT(*wcp)) { 749 (void) _outwch(*wcp); 750 *scp++ = *wcp++; 751 wx++; 752 cx++; 753 754 755 756 757 } 758 } 759 } 760 761 done: 762 if (changed) { 763 /* update the blank structure */ 764 for (wx = 0, scp = curscr->_y[wy]; wx < scrco; ++wx, ++scp) 765 if (_DARKCHAR(*scp)) 766 break; 767 /* LINTED */ 768 _BEGNS[wy] = (short)wx; 769 if (wx == scrco) 770 _ENDNS[wy] = -1; 771 else { 772 wx = scrco - 1; 773 scp = curscr->_y[wy] + wx; 774 for (; wx >= 0; --wx, --scp) 775 if (_DARKCHAR(*scp)) 776 break; 777 /* LINTED */ 778 _ENDNS[wy] = (short)wx; 779 } 780 781 /* update the hash structure */ 782 _CURHASH[wy] = _BEGNS[wy] < scrco ? _NOHASH : 0; 783 } 784 } 785 786 /* 787 * See if a left or right shift is apppropriate 788 * This routine is called only if !cookie_glitch or no video attributes 789 * are used in the affected part. 790 * The main idea is to find a longest common substring which is a 791 * prefix of one of 'wcp' or 'scp', then either delete or 792 * insert depending on where the prefix is. 793 * 794 * wcp : what we want the screen to look like 795 * scp : what the screen looks like now 796 * length: the length to be updated 797 * maxi: maximum possible insert amount 798 * id; *id returns the amount of insert/delete 799 * 800 * Return the number of chars matched after the shift. 801 */ 802 803 static int 804 _useidch(chtype *wcp, chtype *scp, int length, int maxi, int *id) 805 { 806 int x1, x2, blnk, idch, cost, cost_ich1, match; 807 chtype wc; 808 809 /* try deletion */ 810 if (SP->dchok && _CHAR(*wcp) != ' ') { 811 if ((match = _prefix(wcp, scp, length, length / 2, &idch)) > 0) 812 cost = _COST(dcfixed) + (parm_dch ? _COST(Parm_dch) : 813 _COST(Delete_character) * idch); 814 else 815 cost = _INFINITY; 816 817 if (match >= cost) { 818 /* SS: colors */ 819 if (back_color_erase) 820 _turn_off_background(); 821 822 if (SP->dmode) { 823 if (SP->sid_equal) { 824 if (!(SP->phys_irm)) 825 _ONINSERT(); 826 } else { 827 if (SP->phys_irm) 828 _OFFINSERT(); 829 _PUTS(enter_delete_mode, 1); 830 } 831 } 832 833 if (parm_dch) 834 _PUTS(tparm_p1(parm_dch, idch), 1); 835 else 836 for (x1 = 0; x1 < idch; ++x1) 837 _PUTS(delete_character, 1); 838 839 if (SP->dmode) { 840 if (SP->eid_equal) 841 SP->phys_irm = FALSE; 842 _PUTS(exit_delete_mode, 1); 843 } 844 845 /* update screen image */ 846 for (x1 = 0, x2 = idch; x2 < length; ++x1, ++x2) 847 scp[x1] = scp[x2]; 848 for (; x1 < length; ++x1) 849 scp[x1] = ' '; 850 851 *id = -idch; 852 return (match); 853 } 854 } 855 856 /* no insertion wanted or possible */ 857 if (!(SP->ichok) || _CHAR(*scp) == ' ') 858 return (0); 859 860 /* see if insertion is worth it */ 861 maxi = (idch = length / 2) < maxi ? idch : maxi; 862 if ((match = _prefix(scp, wcp, length, maxi, &idch)) <= 0) 863 return (0); 864 865 /* see if inserting blanks only */ 866 for (blnk = 0; blnk < idch; ++blnk) 867 if (wcp[blnk] != ' ') { 868 blnk = 0; 869 break; 870 } 871 872 /* see if doing insertion is worth it */ 873 cost_ich1 = idch * _COST(Insert_character); 874 if (SP->imode) { 875 cost = SP->phys_irm ? 0 : _COST(icfixed); 876 if (blnk > _COST(Parm_ich) && _COST(Parm_ich) < cost_ich1) 877 cost += _COST(Parm_ich); 878 else 879 if (insert_character) 880 cost += cost_ich1; 881 } else { 882 if (parm_ich && _COST(Parm_ich) < cost_ich1) 883 cost = _COST(Parm_ich); 884 else 885 cost = cost_ich1; 886 } 887 if ((cost - blnk) > match) 888 return (0); 889 890 /* perform the insertions */ 891 892 /* SS: colors */ 893 if (back_color_erase) 894 _turn_off_background(); 895 896 if (SP->imode) { 897 if (!SP->phys_irm) 898 _ONINSERT(); 899 if (blnk > _COST(Parm_ich) && _COST(Parm_ich) < cost_ich1) 900 _PUTS(tparm_p1(parm_ich, idch), 1); 901 else 902 if (insert_character) 903 goto do_insert_char; 904 else 905 /* so that we'll do real char insertions */ 906 blnk = 0; 907 } else { 908 if (parm_ich && _COST(Parm_ich) < cost_ich1) 909 _PUTS(tparm_p1(parm_ich, idch), 1); 910 else { 911 do_insert_char: 912 for (x1 = 0; x1 < idch; ++x1) 913 _PUTS(insert_character, 1); 914 } 915 } 916 917 /* inserting desired characters */ 918 if (!blnk) 919 for (x1 = 0; x1 < idch; ++x1) { 920 wc = wcp[x1]; 921 if (_ATTR(wc) != curscr->_attrs) 922 _VIDS(_ATTR(wc), curscr->_attrs); 923 (void) _outwch(_CHAR(wc) == '~' && 924 tilde_glitch ? '`' : wc); 925 ++cx; 926 } 927 928 /* update the screen image */ 929 for (x1 = length - 1, x2 = length - idch - 1; x2 >= 0; --x1, --x2) 930 scp[x1] = scp[x2]; 931 (void) memcpy(scp, wcp, idch * sizeof (chtype)); 932 933 *id = idch; 934 return (match + idch); 935 } 936 937 /* 938 * Find a substring of s2 that match a prefix of s1. 939 * The substring is such that: 940 * 1. it does not start with an element 941 * that is in perfect alignment with one in s1 and 942 * 2: it is at least as long as the displacement. 943 * 944 * length: the length of s1, s2. 945 * maxs: only search for match in [1,maxs] of s2. 946 * begm: *begm returns where the match begins. 947 * 948 * Return the number of matches. 949 */ 950 951 static int 952 _prefix(chtype *s1, chtype *s2, int length, int maxs, int *begm) 953 { 954 int m, n, k; 955 956 n = 0; 957 for (m = 1; m <= maxs; ++m) 958 /* testing for s1[m] != s2[m] is condition 1 */ 959 if (s1[0] == s2[m] && s1[m] != s2[m]) { 960 /* see if it's long enough (condition 2) */ 961 for (k = 2 * m - 1; k > m; --k) 962 if (s1[k - m] != s2[k]) 963 break; 964 /* found a match with a good length */ 965 if (k == m) { 966 *begm = m; 967 968 /* count the # of matches */ 969 s2 += m; 970 length -= m; 971 for (n = m; n < length; ++n) 972 if (s1[n] != s2[n]) 973 break; 974 goto done; 975 } 976 } 977 978 done: 979 return (n); 980 } 981 982 /* Set video markers for cookie terminal. */ 983 984 static void 985 _setmark1(int y, int x, chtype *s) 986 { 987 long a; 988 989 /* set the mark map */ 990 marks[y][x / BITSPERBYTE] |= (1 << (x % BITSPERBYTE)); 991 992 if (s) { 993 a = _VIDEO(curscr->_attrs); 994 995 /* set the video attr of the first char here */ 996 /* LINTED */ 997 *s = _CHAR(*s) | _COLOR(*s) | a; 998 999 /* now the video attr of the rest of the affected interval */ 1000 for (x += 1, s += 1; x < scrco; ++x, ++s) 1001 if (_ISMARK1(y, x)) 1002 break; 1003 else 1004 /* LINTED */ 1005 *s = _CHAR(*s) | _COLOR(*s) | a; 1006 } 1007 } 1008 1009 /* Set color markers for cookie terminal. */ 1010 1011 static void 1012 _setmark2(int y, int x, chtype *s) 1013 { 1014 long a; 1015 1016 /* set the mark map */ 1017 color_marks[y][x / BITSPERBYTE] |= (1 << (x % BITSPERBYTE)); 1018 1019 if (s) { 1020 a = _COLOR(curscr->_attrs); 1021 1022 /* set the video attr of the first char here */ 1023 /* LINTED */ 1024 *s = _CHAR(*s) | _VIDEO(*s) | a; 1025 1026 /* now the video attr of the rest of the affected interval */ 1027 for (x += 1, s += 1; x < scrco; ++x, ++s) 1028 if (_ISMARK2(y, x)) 1029 break; 1030 else 1031 /* LINTED */ 1032 *s = _CHAR(*s) | _VIDEO(*s) | a; 1033 } 1034 } 1035 1036 1037 /* At the right margin various weird things can happen. We treat them here. */ 1038 1039 /* At the right margin various weird things can happen. We treat them here. */ 1040 1041 static void 1042 _rmargin(int wx) 1043 { 1044 int x, w, ix; 1045 chtype sc; 1046 chtype *wcp = _virtscr->_y[cy]; 1047 1048 /* screen may scroll */ 1049 if (cy == scrli - 1) { 1050 /* can't do anything */ 1051 if (!SP->ichok) 1052 return; 1053 1054 /* the width of the new character */ 1055 w = _curs_scrwidth[TYPE(RBYTE(wcp[wx]))]; 1056 /* the place to put it without causing scrolling */ 1057 for (x = wx - 1; x > 0; --x) 1058 if (!ISCBIT(wcp[x])) 1059 break; 1060 sc = curscr->_y[cy][x]; 1061 1062 (void) mvcur(cy, cx, cy, x); 1063 if (_ATTR(wcp[wx]) != curscr->_attrs) 1064 _VIDS(_ATTR(wcp[wx]), curscr->_attrs); 1065 (void) _outwch(tilde_glitch && 1066 _CHAR(wcp[wx]) == '~' ? '`' : wcp[wx]); 1067 1068 for (ix = wx + 1; ix < scrco; ++ix) { 1069 (void) _outwch(wcp[ix]); 1070 } 1071 1072 /* insert sc back in and push wcp[wx] right */ 1073 (void) mvcur(cy, x+w, cy, x); 1074 1075 /* SS: colors */ 1076 if (back_color_erase) 1077 _turn_off_background(); 1078 1079 if (SP->imode && !SP->phys_irm) 1080 _ONINSERT(); 1081 /* width of the old character that was overwritten */ 1082 w = _curs_scrwidth[TYPE(RBYTE(curscr->_y[cy][x]))]; 1083 1084 if (insert_character) 1085 for (ix = 0; ix < w; ++ix) 1086 _PUTS(insert_character, 1); 1087 else 1088 if (parm_ich && !SP->imode) 1089 _PUTS(tparm_p1(parm_ich, w), 1); 1090 1091 if (_ATTR(sc) != curscr->_attrs) 1092 _VIDS(_ATTR(sc), curscr->_attrs); 1093 for (ix = x; w > 0; --w, ++ix) 1094 (void) _outwch(curscr->_y[cy][ix]); 1095 1096 /* make sure the video attrs are ok */ 1097 if (marks && (_ATTR(sc) || _ATTR(wcp[wx]))) 1098 _VIDS(_ATTR(wcp[wx]), ~_ATTR(sc)); 1099 1100 /* update screen image */ 1101 /* LINTED */ 1102 cx = (short)wx; 1103 curscr->_y[cy][wx] = wcp[wx]; 1104 for (x = wx + 1; x < scrco; ++x) { 1105 (void) _outwch(wcp[x]); 1106 curscr->_y[cy][x] = wcp[x]; 1107 } 1108 return; 1109 } 1110 1111 /* put char out and update screen image */ 1112 (void) _outwch(tilde_glitch && _CHAR(wcp[wx]) == '~' ? '`' : wcp[wx]); 1113 1114 1115 1116 1117 1118 1119 1120 1121 curscr->_y[cy][wx] = wcp[wx]; 1122 1123 for (x = wx + 1; x < scrco; ++x) { 1124 (void) _outwch(wcp[x]); 1125 curscr->_y[cy][x] = wcp[x]; 1126 } 1127 1128 /* make sure that wrap-around happens */ 1129 if (!auto_right_margin || eat_newline_glitch) { 1130 (void) _outch('\r'); 1131 (void) _outch('\n'); 1132 } 1133 cx = 0; 1134 ++cy; 1135 } 1136 1137 /* 1138 * Find the top-most line to do clear-to-eod. 1139 * 1140 * topy, boty: the region to consider 1141 */ 1142 1143 static int 1144 _getceod(int topy, int boty) 1145 { 1146 chtype *wcp, *ecp; 1147 int wy; 1148 short *begch, *endch, *begns; 1149 1150 /* do nothing */ 1151 if ((topy + 1) >= boty) 1152 return (boty); 1153 1154 wy = boty - 1; 1155 begch = _virtscr->_firstch + wy; 1156 endch = _virtscr->_lastch + wy; 1157 begns = _BEGNS + wy; 1158 1159 for (; wy >= topy; --wy, --begch, --endch, --begns) { 1160 if (*endch == _BLANK || (*begch >= scrco && *begns >= scrco)) 1161 continue; 1162 1163 wcp = _virtscr->_y[wy]; 1164 ecp = wcp + scrco; 1165 for (; wcp < ecp; ++wcp) 1166 if (_DARKCHAR(*wcp)) 1167 break; 1168 if (wcp != ecp) 1169 break; 1170 1171 *endch = _BLANK; 1172 } 1173 1174 return (wy + 1); 1175 } 1176 1177 /* Use hardware clear-to-bottom. */ 1178 1179 static void 1180 _useceod(int topy, int boty) 1181 { 1182 short *begns, *begch; 1183 1184 /* skip lines already blanked */ 1185 begch = _virtscr->_firstch + topy; 1186 begns = _BEGNS + topy; 1187 for (; topy < boty; ++topy, ++begns, ++begch) 1188 if (*begns < scrco || *begch == _REDRAW) 1189 break; 1190 else 1191 *begch = _INFINITY; 1192 1193 /* nothing to do */ 1194 if (topy + 1 >= boty) 1195 return; 1196 1197 /* see if bottom is clear */ 1198 for (begns = _BEGNS + boty; boty < scrli; ++boty, ++begns) 1199 if (*begns < scrco) 1200 return; 1201 1202 /* use clear-screen if appropriate */ 1203 if (topy == 0) { 1204 /* SS: colors */ 1205 if (back_color_erase) 1206 _turn_off_background(); 1207 1208 _PUTS(clear_screen, scrli); 1209 cy = 0; cx = 0; 1210 (void) werase(curscr); 1211 } else { 1212 1213 /* use clear-to-end-of-display or delete lines */ 1214 if (clr_eos || (parm_delete_line && !memory_below)) { 1215 (void) mvcur(cy, cx, topy, 0); 1216 /* LINTED */ 1217 cy = (short)topy; 1218 cx = 0; 1219 /* SS: colors */ 1220 if (back_color_erase) 1221 _turn_off_background(); 1222 _PUTS(clr_eos ? clr_eos : tparm_p1(parm_delete_line, 1223 scrli - topy), scrli - topy); 1224 1225 /* update curscr */ 1226 /* LINTED */ 1227 curscr->_cury = (short)topy; 1228 curscr->_curx = 0; 1229 (void) wclrtobot(curscr); 1230 } else { 1231 /* no hardware support */ 1232 return; 1233 } 1234 } 1235 1236 /* correct the update structure */ 1237 (void) wtouchln(_virtscr, topy, scrli, FALSE); 1238 } 1239 1240 1241 static void 1242 _turn_off_background(void) 1243 { 1244 /* this routine turn the background color to zero. This need to be */ 1245 /* done only in forllowing cases: */ 1246 /* 1) We are using Tek type terminal (which has bce terminfo */ 1247 /* variable) */ 1248 /* 2) The current background is not already zero */ 1249 1250 if (set_background && cur_term->_cur_pair.background > 0) { 1251 _PUTS(orig_pair, 1); 1252 cur_term->_cur_pair.foreground = -1; 1253 cur_term->_cur_pair.background = -1; 1254 curscr->_attrs &= ~A_COLOR; 1255 } 1256 } 1257