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