1 /* $NetBSD: refresh.c,v 1.80 2016/01/10 08:11:06 jdc Exp $ */ 2 3 /* 4 * Copyright (c) 1981, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94"; 36 #else 37 __RCSID("$NetBSD: refresh.c,v 1.80 2016/01/10 08:11:06 jdc Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include "curses.h" 45 #include "curses_private.h" 46 47 static void domvcur(int, int, int, int); 48 static int makech(int); 49 static void quickch(void); 50 static void scrolln(int, int, int, int, int); 51 52 static int _cursesi_wnoutrefresh(SCREEN *, WINDOW *, 53 int, int, int, int, int, int); 54 55 #ifdef HAVE_WCHAR 56 int cellcmp( __LDATA *, __LDATA * ); 57 int linecmp( __LDATA *, __LDATA *, size_t ); 58 #endif /* HAVE_WCHAR */ 59 60 #ifndef _CURSES_USE_MACROS 61 62 /* 63 * refresh -- 64 * Make the current screen look like "stdscr" over the area covered by 65 * stdscr. 66 */ 67 int 68 refresh(void) 69 { 70 return wrefresh(stdscr); 71 } 72 73 #endif 74 75 /* 76 * wnoutrefresh -- 77 * Add the contents of "win" to the virtual window. 78 */ 79 int 80 wnoutrefresh(WINDOW *win) 81 { 82 #ifdef DEBUG 83 __CTRACE(__CTRACE_REFRESH, "wnoutrefresh: win %p\n", win); 84 #endif 85 86 return _cursesi_wnoutrefresh(_cursesi_screen, win, 0, 0, win->begy, 87 win->begx, win->maxy, win->maxx); 88 } 89 90 /* 91 * pnoutrefresh -- 92 * Add the contents of "pad" to the virtual window. 93 */ 94 int 95 pnoutrefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx, 96 int smaxy, int smaxx) 97 { 98 int pmaxy, pmaxx; 99 100 #ifdef DEBUG 101 __CTRACE(__CTRACE_REFRESH, "pnoutrefresh: pad %p, flags 0x%08x\n", 102 pad, pad->flags); 103 __CTRACE(__CTRACE_REFRESH, 104 "pnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n", 105 pbegy, pbegx, sbegy, sbegx, smaxy, smaxx); 106 #endif 107 108 /* SUS says if these are negative, they should be treated as zero */ 109 if (pbegy < 0) 110 pbegy = 0; 111 if (pbegx < 0) 112 pbegx = 0; 113 if (sbegy < 0) 114 sbegy = 0; 115 if (sbegx < 0) 116 sbegx = 0; 117 118 /* Calculate rectangle on pad - used by _cursesi_wnoutrefresh */ 119 pmaxy = pbegy + smaxy - sbegy + 1; 120 pmaxx = pbegx + smaxx - sbegx + 1; 121 122 /* Check rectangle fits in pad */ 123 if (pmaxy > pad->maxy - pad->begy) 124 pmaxy = pad->maxy - pad->begy; 125 if (pmaxx > pad->maxx - pad->begx) 126 pmaxx = pad->maxx - pad->begx; 127 128 if (smaxy - sbegy < 0 || smaxx - sbegx < 0 ) 129 return ERR; 130 131 return _cursesi_wnoutrefresh(_cursesi_screen, pad, 132 pad->begy + pbegy, pad->begx + pbegx, pad->begy + sbegy, 133 pad->begx + sbegx, pmaxy, pmaxx); 134 } 135 136 /* 137 * _cursesi_wnoutrefresh -- 138 * Does the grunt work for wnoutrefresh to the given screen. 139 * Copies the part of the window given by the rectangle 140 * (begy, begx) to (maxy, maxx) at screen position (wbegy, wbegx). 141 */ 142 int 143 _cursesi_wnoutrefresh(SCREEN *screen, WINDOW *win, int begy, int begx, 144 int wbegy, int wbegx, int maxy, int maxx) 145 { 146 147 short sy, wy, wx, y_off, x_off, mx, dy_off, dx_off, endy; 148 __LINE *wlp, *vlp, *dwlp; 149 WINDOW *sub_win, *orig, *swin, *dwin; 150 151 #ifdef DEBUG 152 __CTRACE(__CTRACE_REFRESH, "_wnoutrefresh: win %p, flags 0x%08x\n", 153 win, win->flags); 154 __CTRACE(__CTRACE_REFRESH, 155 "_wnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n", 156 begy, begx, wbegy, wbegx, maxy, maxx); 157 #endif 158 159 if (screen->curwin) 160 return OK; 161 162 swin = dwin = win; 163 if (win->flags & __ISDERWIN) 164 swin = win->orig; 165 166 /* 167 * Recurse through any sub-windows, mark as dirty lines on the parent 168 * window that are dirty on the sub-window and clear the dirty flag on 169 * the sub-window. 170 */ 171 if (dwin->orig == 0) { 172 orig = dwin; 173 for (sub_win = dwin->nextp; sub_win != orig; 174 sub_win = sub_win->nextp) { 175 if (sub_win->flags & __ISDERWIN) 176 continue; 177 #ifdef DEBUG 178 __CTRACE(__CTRACE_REFRESH, 179 "wnout_refresh: win %p, sub_win %p\n", 180 orig, sub_win); 181 #endif 182 for (sy = 0; sy < sub_win->maxy; sy++) { 183 if (sub_win->alines[sy]->flags & __ISDIRTY) { 184 orig->alines[sy + sub_win->begy - orig->begy]->flags 185 |= __ISDIRTY; 186 sub_win->alines[sy]->flags 187 &= ~__ISDIRTY; 188 } 189 if (sub_win->alines[sy]->flags & __ISFORCED) { 190 orig->alines[sy + sub_win->begy - orig->begy]->flags 191 |= __ISFORCED; 192 sub_win->alines[sy]->flags 193 &= ~__ISFORCED; 194 } 195 } 196 } 197 } 198 199 /* Check that cursor position on "win" is valid for "__virtscr" */ 200 if (dwin->cury + wbegy - begy < screen->__virtscr->maxy && 201 dwin->cury + wbegy - begy >= 0 && dwin->cury < maxy - begy) 202 screen->__virtscr->cury = dwin->cury + wbegy - begy; 203 if (dwin->curx + wbegx - begx < screen->__virtscr->maxx && 204 dwin->curx + wbegx - begx >= 0 && dwin->curx < maxx - begx) 205 screen->__virtscr->curx = dwin->curx + wbegx - begx; 206 207 /* Copy the window flags from "win" to "__virtscr" */ 208 if (dwin->flags & __CLEAROK) { 209 if (dwin->flags & __FULLWIN) 210 screen->__virtscr->flags |= __CLEAROK; 211 dwin->flags &= ~__CLEAROK; 212 } 213 screen->__virtscr->flags &= ~__LEAVEOK; 214 screen->__virtscr->flags |= dwin->flags; 215 216 if ((dwin->flags & __ISDERWIN) != 0) 217 endy = begy + maxy; 218 else 219 endy = maxy; 220 221 for (wy = begy, y_off = wbegy, dy_off = 0; wy < endy && 222 y_off < screen->__virtscr->maxy; wy++, y_off++, dy_off++) { 223 wlp = swin->alines[wy]; 224 dwlp = dwin->alines[dy_off]; 225 #ifdef DEBUG 226 __CTRACE(__CTRACE_REFRESH, 227 "_wnoutrefresh: wy %d\tf %d\tl %d\tflags %x\n", 228 wy, *wlp->firstchp, *wlp->lastchp, wlp->flags); 229 230 if ((dwin->flags & __ISDERWIN) != 0) { 231 __CTRACE(__CTRACE_REFRESH, 232 "_wnoutrefresh: derwin wy %d\tf %d\tl %d\tflags %x\n", 233 dy_off, *dwlp->firstchp, *dwlp->lastchp, dwlp->flags); 234 __CTRACE(__CTRACE_REFRESH, 235 "_wnoutrefresh: derwin maxx %d\tch_off %d\n", 236 dwin->maxx, dwin->ch_off); 237 } 238 #endif 239 if (((wlp->flags & (__ISDIRTY | __ISFORCED)) == 0) && 240 ((dwlp->flags & (__ISDIRTY | __ISFORCED)) == 0)) 241 continue; 242 vlp = screen->__virtscr->alines[y_off]; 243 244 if ((*wlp->firstchp < maxx + swin->ch_off && 245 *wlp->lastchp >= swin->ch_off) || 246 ((((dwin->flags & __ISDERWIN) != 0) && 247 (*dwlp->firstchp < dwin->maxx + dwin->ch_off && 248 *dwlp->lastchp >= dwin->ch_off)))) { 249 /* Set start column */ 250 wx = begx; 251 x_off = wbegx; 252 dx_off = 0; 253 /* 254 * if a derwin then source change pointers aren't 255 * relevant. 256 */ 257 if ((dwin->flags & __ISDERWIN) != 0) 258 mx = wx + maxx; 259 else { 260 if (*wlp->firstchp - swin->ch_off > 0) { 261 wx += *wlp->firstchp - swin->ch_off; 262 x_off += *wlp->firstchp - swin->ch_off; 263 } 264 mx = maxx; 265 if (mx > *wlp->lastchp - swin->ch_off + 1) 266 mx = *dwlp->lastchp - dwin->ch_off + 1; 267 if (x_off + (mx - wx) > __virtscr->maxx) 268 mx -= (x_off + maxx) - __virtscr->maxx; 269 } 270 271 /* Copy line from "win" to "__virtscr". */ 272 while (wx < mx) { 273 #ifdef DEBUG 274 __CTRACE(__CTRACE_REFRESH, 275 "_wnoutrefresh: copy from %d, " 276 "%d to %d, %d: %s, 0x%x", 277 wy, wx, y_off, x_off, 278 unctrl(wlp->line[wx].ch), 279 wlp->line[wx].attr); 280 #endif 281 /* Copy character */ 282 vlp->line[x_off].ch = wlp->line[wx].ch; 283 /* Copy attributes */ 284 vlp->line[x_off].attr = wlp->line[wx].attr; 285 /* Check for nca conflict with colour */ 286 if ((vlp->line[x_off].attr & __COLOR) && 287 (vlp->line[x_off].attr & 288 _cursesi_screen->nca)) 289 vlp->line[x_off].attr &= ~__COLOR; 290 if (win->flags & __ISDERWIN) { 291 dwlp->line[dx_off].ch = 292 wlp->line[wx].ch; 293 dwlp->line[dx_off].attr = 294 wlp->line[wx].attr; 295 } 296 297 #ifdef HAVE_WCHAR 298 if (wlp->line[wx].ch 299 == (wchar_t)btowc((int) win->bch)) { 300 vlp->line[x_off].ch = win->bch; 301 SET_WCOL( vlp->line[x_off], 1 ); 302 if (_cursesi_copy_nsp(win->bnsp, 303 &vlp->line[x_off]) 304 == ERR) 305 return ERR; 306 if (win->flags & __ISDERWIN) { 307 dwlp->line[dx_off].ch = 308 win->bch; 309 SET_WCOL(dwlp->line[dx_off], 1); 310 if (_cursesi_copy_nsp(win->bnsp, 311 &dwlp->line[dx_off]) 312 == ERR) 313 return ERR; 314 } 315 } 316 #endif /* HAVE_WCHAR */ 317 #ifdef DEBUG 318 __CTRACE(__CTRACE_REFRESH, " = %s, 0x%x\n", 319 unctrl(vlp->line[x_off].ch), 320 vlp->line[x_off].attr); 321 #endif 322 wx++; 323 x_off++; 324 dx_off++; 325 } 326 327 /* Set flags on "__virtscr" and unset on "win". */ 328 if (wlp->flags & __ISPASTEOL) 329 vlp->flags |= __ISPASTEOL; 330 else 331 vlp->flags &= ~__ISPASTEOL; 332 if (wlp->flags & __ISDIRTY) 333 vlp->flags |= __ISDIRTY; 334 if (wlp->flags & __ISFORCED) 335 vlp->flags |= __ISFORCED; 336 337 #ifdef DEBUG 338 __CTRACE(__CTRACE_REFRESH, 339 "win: firstch = %d, lastch = %d\n", 340 *wlp->firstchp, *wlp->lastchp); 341 if (win->flags & __ISDERWIN) { 342 __CTRACE(__CTRACE_REFRESH, 343 "derwin: fistch = %d, lastch = %d\n", 344 *dwlp->firstchp, *dwlp->lastchp); 345 } 346 #endif 347 /* Set change pointers on "__virtscr". */ 348 if (*vlp->firstchp > 349 *wlp->firstchp + wbegx - win->ch_off) 350 *vlp->firstchp = 351 *wlp->firstchp + wbegx - win->ch_off; 352 if (*vlp->lastchp < 353 *wlp->lastchp + wbegx - win->ch_off) 354 *vlp->lastchp = 355 *wlp->lastchp + wbegx - win->ch_off; 356 357 if (win->flags & __ISDERWIN) { 358 if (*vlp->firstchp > 359 *dwlp->firstchp + wbegx - dwin->ch_off) { 360 *vlp->firstchp = 361 *dwlp->firstchp + wbegx 362 - dwin->ch_off; 363 vlp->flags |= __ISDIRTY; 364 } 365 366 if (*vlp->lastchp < 367 *dwlp->lastchp + wbegx - dwin->ch_off) { 368 *vlp->lastchp = *dwlp->lastchp 369 + wbegx - dwin->ch_off; 370 vlp->flags |= __ISDIRTY; 371 } 372 } 373 374 #ifdef DEBUG 375 __CTRACE(__CTRACE_REFRESH, 376 "__virtscr: firstch = %d, lastch = %d\n", 377 *vlp->firstchp, *vlp->lastchp); 378 #endif 379 /* 380 * Unset change pointers only if a window and we 381 * are not forcing a redraw. A pad can be displayed 382 * again without any of the contents changing. 383 */ 384 if ((!(win->flags & __ISPAD)) || 385 ((wlp->flags & __ISFORCED) == __ISFORCED)) { 386 /* Set change pointers on "win". */ 387 if (*wlp->firstchp >= win->ch_off) 388 *wlp->firstchp = maxx + win->ch_off; 389 if (*wlp->lastchp < maxx + win->ch_off) 390 *wlp->lastchp = win->ch_off; 391 if ((*wlp->lastchp < *wlp->firstchp) || 392 (*wlp->firstchp >= maxx + win->ch_off) || 393 (*wlp->lastchp <= win->ch_off)) { 394 #ifdef DEBUG 395 __CTRACE(__CTRACE_REFRESH, 396 "_wnoutrefresh: " 397 "line %d notdirty\n", wy); 398 #endif 399 wlp->flags &= ~(__ISDIRTY | __ISFORCED); 400 } 401 } 402 } 403 } 404 return OK; 405 } 406 407 /* 408 * wrefresh -- 409 * Make the current screen look like "win" over the area covered by 410 * win. 411 */ 412 int 413 wrefresh(WINDOW *win) 414 { 415 int retval; 416 int pbegx, pbegy; 417 418 #ifdef DEBUG 419 __CTRACE(__CTRACE_REFRESH, "wrefresh: win %p\n", win); 420 #endif 421 422 _cursesi_screen->curwin = (win == _cursesi_screen->curscr); 423 if (!_cursesi_screen->curwin) { 424 pbegx = pbegy = 0; 425 if ((win->flags & __ISDERWIN) == __ISDERWIN) { 426 pbegx = win->derx; 427 pbegy = win->dery; 428 #ifdef DEBUG 429 __CTRACE(__CTRACE_REFRESH, "wrefresh: derwin, begy = %d, begx = %x\n", 430 pbegy, pbegx); 431 #endif 432 } 433 retval = _cursesi_wnoutrefresh(_cursesi_screen, win, pbegy, 434 pbegx, win->begy, win->begx, win->maxy, win->maxx); 435 } else 436 retval = OK; 437 if (retval == OK) { 438 retval = doupdate(); 439 if (!(win->flags & __LEAVEOK)) { 440 win->cury = max(0, curscr->cury - win->begy); 441 win->curx = max(0, curscr->curx - win->begx); 442 } 443 } 444 _cursesi_screen->curwin = 0; 445 return(retval); 446 } 447 448 /* 449 * prefresh -- 450 * Make the current screen look like "pad" over the area coverd by 451 * the specified area of pad. 452 */ 453 int 454 prefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx, 455 int smaxy, int smaxx) 456 { 457 int retval; 458 459 #ifdef DEBUG 460 __CTRACE(__CTRACE_REFRESH, "prefresh: pad %p, flags 0x%08x\n", 461 pad, pad->flags); 462 #endif 463 /* Retain values in case pechochar() is called. */ 464 pad->pbegy = pbegy; 465 pad->pbegx = pbegx; 466 pad->sbegy = sbegy; 467 pad->sbegx = sbegx; 468 pad->smaxy = smaxy; 469 pad->smaxx = smaxx; 470 471 /* Use pnoutrefresh() to avoid duplicating code here */ 472 retval = pnoutrefresh(pad, pbegy, pbegx, sbegy, sbegx, smaxy, smaxx); 473 if (retval == OK) { 474 retval = doupdate(); 475 if (!(pad->flags & __LEAVEOK)) { 476 pad->cury = max(0, curscr->cury - pad->begy); 477 pad->curx = max(0, curscr->curx - pad->begx); 478 } 479 } 480 return(retval); 481 } 482 483 /* 484 * doupdate -- 485 * Make the current screen look like the virtual window "__virtscr". 486 */ 487 int 488 doupdate(void) 489 { 490 WINDOW *win; 491 __LINE *wlp, *vlp; 492 short wy; 493 int dnum, was_cleared; 494 #ifdef HAVE_WCHAR 495 __LDATA *lp; 496 nschar_t *np; 497 int x; 498 #endif /* HAVE_WCHAR */ 499 500 /* Check if we need to restart ... */ 501 if (_cursesi_screen->endwin) 502 __restartwin(); 503 504 if (_cursesi_screen->curwin) 505 win = curscr; 506 else 507 win = _cursesi_screen->__virtscr; 508 509 /* Initialize loop parameters. */ 510 _cursesi_screen->ly = curscr->cury; 511 _cursesi_screen->lx = curscr->curx; 512 wy = 0; 513 514 if (!_cursesi_screen->curwin) { 515 for (wy = 0; wy < win->maxy; wy++) { 516 wlp = win->alines[wy]; 517 if (wlp->flags & __ISDIRTY) { 518 #ifndef HAVE_WCHAR 519 wlp->hash = __hash(wlp->line, 520 (size_t)(win->maxx * __LDATASIZE)); 521 #else 522 wlp->hash = 0; 523 for ( x = 0; x < win->maxx; x++ ) { 524 lp = &wlp->line[ x ]; 525 wlp->hash = __hash_more( &lp->ch, 526 sizeof( wchar_t ), wlp->hash ); 527 wlp->hash = __hash_more( &lp->attr, 528 sizeof( attr_t ), wlp->hash ); 529 np = lp->nsp; 530 if (np) { 531 while ( np ) { 532 wlp->hash 533 = __hash_more( 534 &np->ch, 535 sizeof(wchar_t), 536 wlp->hash ); 537 np = np->next; 538 } 539 } 540 } 541 #endif /* HAVE_WCHAR */ 542 } 543 } 544 } 545 546 was_cleared = 0; 547 if ((win->flags & __CLEAROK) || (curscr->flags & __CLEAROK) || 548 _cursesi_screen->curwin) { 549 if (curscr->wattr & __COLOR) 550 __unsetattr(0); 551 tputs(clear_screen, 0, __cputchar); 552 _cursesi_screen->ly = 0; 553 _cursesi_screen->lx = 0; 554 if (!_cursesi_screen->curwin) { 555 curscr->flags &= ~__CLEAROK; 556 curscr->cury = 0; 557 curscr->curx = 0; 558 werase(curscr); 559 } 560 __touchwin(win); 561 win->flags &= ~__CLEAROK; 562 /* note we cleared for later */ 563 was_cleared = 1; 564 } 565 if (!cursor_address) { 566 if (win->curx != 0) 567 __cputchar('\n'); 568 if (!_cursesi_screen->curwin) 569 werase(curscr); 570 } 571 #ifdef DEBUG 572 __CTRACE(__CTRACE_REFRESH, "doupdate: (%p): curwin = %d\n", win, 573 _cursesi_screen->curwin); 574 __CTRACE(__CTRACE_REFRESH, "doupdate: \tfirstch\tlastch\n"); 575 #endif 576 577 if (!_cursesi_screen->curwin) { 578 /* 579 * Invoke quickch() only if more than a quarter of the lines 580 * in the window are dirty. 581 */ 582 for (wy = 0, dnum = 0; wy < win->maxy; wy++) 583 if (win->alines[wy]->flags & __ISDIRTY) 584 dnum++; 585 if (!__noqch && dnum > (int) win->maxy / 4) 586 quickch(); 587 } 588 589 #ifdef DEBUG 590 { 591 int i, j; 592 593 __CTRACE(__CTRACE_REFRESH, 594 "#####################################\n"); 595 __CTRACE(__CTRACE_REFRESH, 596 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n", 597 stdscr, curscr, _cursesi_screen->__virtscr); 598 for (i = 0; i < curscr->maxy; i++) { 599 __CTRACE(__CTRACE_REFRESH, "C: %d:", i); 600 __CTRACE(__CTRACE_REFRESH, " 0x%x \n", 601 curscr->alines[i]->hash); 602 for (j = 0; j < curscr->maxx; j++) 603 __CTRACE(__CTRACE_REFRESH, "%c", 604 curscr->alines[i]->line[j].ch); 605 __CTRACE(__CTRACE_REFRESH, "\n"); 606 __CTRACE(__CTRACE_REFRESH, " attr:"); 607 for (j = 0; j < curscr->maxx; j++) 608 __CTRACE(__CTRACE_REFRESH, " %x", 609 curscr->alines[i]->line[j].attr); 610 __CTRACE(__CTRACE_REFRESH, "\n"); 611 __CTRACE(__CTRACE_REFRESH, "W: %d:", i); 612 __CTRACE(__CTRACE_REFRESH, " 0x%x \n", 613 win->alines[i]->hash); 614 __CTRACE(__CTRACE_REFRESH, " 0x%x ", 615 win->alines[i]->flags); 616 for (j = 0; j < win->maxx; j++) 617 __CTRACE(__CTRACE_REFRESH, "%c", 618 win->alines[i]->line[j].ch); 619 __CTRACE(__CTRACE_REFRESH, "\n"); 620 __CTRACE(__CTRACE_REFRESH, " attr:"); 621 for (j = 0; j < win->maxx; j++) 622 __CTRACE(__CTRACE_REFRESH, " %x", 623 win->alines[i]->line[j].attr); 624 __CTRACE(__CTRACE_REFRESH, "\n"); 625 #ifdef HAVE_WCHAR 626 __CTRACE(__CTRACE_REFRESH, " nsp:"); 627 for (j = 0; j < curscr->maxx; j++) 628 __CTRACE(__CTRACE_REFRESH, " %p", 629 win->alines[i]->line[j].nsp); 630 __CTRACE(__CTRACE_REFRESH, "\n"); 631 __CTRACE(__CTRACE_REFRESH, " bnsp:"); 632 for (j = 0; j < curscr->maxx; j++) 633 __CTRACE(__CTRACE_REFRESH, " %p", 634 win->bnsp); 635 __CTRACE(__CTRACE_REFRESH, "\n"); 636 #endif /* HAVE_WCHAR */ 637 } 638 } 639 #endif /* DEBUG */ 640 641 for (wy = 0; wy < win->maxy; wy++) { 642 wlp = win->alines[wy]; 643 vlp = _cursesi_screen->__virtscr->alines[win->begy + wy]; 644 /* XXX: remove this debug */ 645 #ifdef DEBUG 646 __CTRACE(__CTRACE_REFRESH, 647 "doupdate: wy %d\tf: %d\tl:%d\tflags %x\n", 648 wy, *wlp->firstchp, *wlp->lastchp, wlp->flags); 649 #endif /* DEBUG */ 650 if (!_cursesi_screen->curwin) 651 curscr->alines[wy]->hash = wlp->hash; 652 if ((wlp->flags & __ISDIRTY) || 653 (wlp->flags & __ISFORCED)) { 654 #ifdef DEBUG 655 __CTRACE(__CTRACE_REFRESH, 656 "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy, 657 *wlp->firstchp, *wlp->lastchp); 658 #endif /* DEBUG */ 659 /* 660 * We have just cleared so don't force an update 661 * otherwise we spray neeedless blanks to a cleared 662 * screen. 663 */ 664 if (was_cleared == 1) 665 win->alines[wy]->flags &= ~__ISFORCED; 666 667 if (makech(wy) == ERR) 668 return (ERR); 669 else { 670 if (*wlp->firstchp >= 0) 671 *wlp->firstchp = win->maxx; 672 if (*wlp->lastchp < win->maxx) 673 *wlp->lastchp = win->ch_off; 674 if (*wlp->lastchp < *wlp->firstchp) { 675 #ifdef DEBUG 676 __CTRACE(__CTRACE_REFRESH, 677 "doupdate: line %d notdirty\n", wy); 678 #endif /* DEBUG */ 679 wlp->flags &= ~(__ISDIRTY | __ISFORCED); 680 } 681 } 682 } 683 684 /* 685 * virtscr is now synced for the line, unset the change 686 * pointers. 687 */ 688 if (*vlp->firstchp >= 0) 689 *vlp->firstchp = _cursesi_screen->__virtscr->maxx; 690 if (*vlp->lastchp <= _cursesi_screen->__virtscr->maxx) 691 *vlp->lastchp = 0; 692 693 #ifdef DEBUG 694 __CTRACE(__CTRACE_REFRESH, "\t%d\t%d\n", 695 *wlp->firstchp, *wlp->lastchp); 696 #endif /* DEBUG */ 697 } 698 699 #ifdef DEBUG 700 __CTRACE(__CTRACE_REFRESH, "doupdate: ly=%d, lx=%d\n", 701 _cursesi_screen->ly, _cursesi_screen->lx); 702 #endif /* DEBUG */ 703 704 if (_cursesi_screen->curwin) 705 domvcur(_cursesi_screen->ly, _cursesi_screen->lx, 706 win->cury, win->curx); 707 else { 708 if (win->flags & __LEAVEOK) { 709 curscr->cury = _cursesi_screen->ly; 710 curscr->curx = _cursesi_screen->lx; 711 } else { 712 domvcur(_cursesi_screen->ly, _cursesi_screen->lx, 713 win->cury, win->curx); 714 curscr->cury = win->cury; 715 curscr->curx = win->curx; 716 } 717 } 718 719 /* Don't leave the screen with attributes set. */ 720 __unsetattr(0); 721 #ifdef DEBUG 722 #ifdef HAVE_WCHAR 723 { 724 int i, j; 725 726 __CTRACE(__CTRACE_REFRESH, 727 "***********after*****************\n"); 728 __CTRACE(__CTRACE_REFRESH, 729 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n", 730 stdscr, curscr, _cursesi_screen->__virtscr); 731 for (i = 0; i < curscr->maxy; i++) { 732 for (j = 0; j < curscr->maxx; j++) 733 __CTRACE(__CTRACE_REFRESH, 734 "[%d,%d](%x,%x,%p)-(%x,%x,%p)\n", 735 i, j, 736 curscr->alines[i]->line[j].ch, 737 curscr->alines[i]->line[j].attr, 738 curscr->alines[i]->line[j].nsp, 739 _cursesi_screen->__virtscr->alines[i]->line[j].ch, 740 _cursesi_screen->__virtscr->alines[i]->line[j].attr, 741 _cursesi_screen->__virtscr->alines[i]->line[j].nsp); 742 } 743 } 744 #endif /* HAVE_WCHAR */ 745 #endif /* DEBUG */ 746 return fflush(_cursesi_screen->outfd) == EOF ? ERR : OK; 747 } 748 749 /* 750 * makech -- 751 * Make a change on the screen. 752 */ 753 static int 754 makech(int wy) 755 { 756 WINDOW *win; 757 static __LDATA blank; 758 __LDATA *nsp, *csp, *cp, *cep; 759 __LINE *wlp; 760 size_t clsp, nlsp; /* Last space in lines. */ 761 int lch, wx; 762 const char *ce; 763 attr_t lspc; /* Last space colour */ 764 attr_t off, on; 765 766 #ifdef __GNUC__ 767 nlsp = lspc = 0; /* XXX gcc -Wuninitialized */ 768 #endif 769 if (_cursesi_screen->curwin) 770 win = curscr; 771 else 772 win = __virtscr; 773 #ifdef HAVE_WCHAR 774 blank.ch = ( wchar_t )btowc(( int ) win->bch ); 775 blank.attr = 0; 776 if (_cursesi_copy_nsp(win->bnsp, &blank) == ERR) 777 return ERR; 778 SET_WCOL( blank, 1 ); 779 #endif /* HAVE_WCHAR */ 780 #ifdef DEBUG 781 #if HAVE_WCHAR 782 { 783 int x; 784 __LDATA *lp, *vlp; 785 786 __CTRACE(__CTRACE_REFRESH, 787 "[makech-before]wy=%d,curscr(%p)-__virtscr(%p)\n", 788 wy, curscr, __virtscr); 789 for (x = 0; x < curscr->maxx; x++) { 790 lp = &curscr->alines[wy]->line[x]; 791 vlp = &__virtscr->alines[wy]->line[x]; 792 __CTRACE(__CTRACE_REFRESH, 793 "[%d,%d](%x,%x,%x,%x,%p)-" 794 "(%x,%x,%x,%x,%p)\n", 795 wy, x, lp->ch, lp->attr, 796 win->bch, win->battr, lp->nsp, 797 vlp->ch, vlp->attr, 798 win->bch, win->battr, vlp->nsp); 799 } 800 } 801 #endif /* HAVE_WCHAR */ 802 #endif /* DEBUG */ 803 /* Is the cursor still on the end of the last line? */ 804 if (wy > 0 && curscr->alines[wy - 1]->flags & __ISPASTEOL) { 805 domvcur(_cursesi_screen->ly, _cursesi_screen->lx, 806 _cursesi_screen->ly + 1, 0); 807 _cursesi_screen->ly++; 808 _cursesi_screen->lx = 0; 809 } 810 wlp = win->alines[wy]; 811 wx = *win->alines[wy]->firstchp; 812 if (wx < 0) 813 wx = 0; 814 else 815 if (wx >= win->maxx) 816 return (OK); 817 lch = *win->alines[wy]->lastchp; 818 if (lch < 0) 819 return (OK); 820 else 821 if (lch >= (int) win->maxx) 822 lch = win->maxx - 1; 823 824 if (_cursesi_screen->curwin) { 825 csp = ␣ 826 #ifdef DEBUG 827 __CTRACE(__CTRACE_REFRESH, "makech: csp is blank\n"); 828 #endif /* DEBUG */ 829 } else { 830 csp = &curscr->alines[wy]->line[wx]; 831 #ifdef DEBUG 832 __CTRACE(__CTRACE_REFRESH, 833 "makech: csp is on curscr:(%d,%d)\n", wy, wx); 834 #endif /* DEBUG */ 835 } 836 837 nsp = &win->alines[wy]->line[wx]; 838 #ifdef DEBUG 839 if ( _cursesi_screen->curwin ) 840 __CTRACE(__CTRACE_REFRESH, 841 "makech: nsp is at curscr:(%d,%d)\n", wy, wx); 842 else 843 __CTRACE(__CTRACE_REFRESH, 844 "makech: nsp is at __virtscr:(%d,%d)\n", wy, wx); 845 #endif /* DEBUG */ 846 if (clr_eol && !_cursesi_screen->curwin) { 847 cp = &win->alines[wy]->line[win->maxx - 1]; 848 lspc = cp->attr & __COLOR; 849 #ifndef HAVE_WCHAR 850 while (cp->ch == ' ' && cp->attr == lspc) /* XXX */ 851 if (cp-- <= win->alines[wy]->line) 852 break; 853 #else 854 while (cp->ch == ( wchar_t )btowc(( int )' ' ) 855 && ( cp->attr & WA_ATTRIBUTES ) == lspc) 856 if (cp-- <= win->alines[wy]->line) 857 break; 858 #endif /* HAVE_WCHAR */ 859 if (win->alines[wy]->line > cp) 860 nlsp = 0; 861 else 862 nlsp = cp - win->alines[wy]->line; 863 } 864 if (!_cursesi_screen->curwin) 865 ce = clr_eol; 866 else 867 ce = NULL; 868 869 while (wx <= lch) { 870 #ifdef DEBUG 871 __CTRACE(__CTRACE_REFRESH, "makech: wx=%d,lch=%d\n", wx, lch); 872 #endif /* DEBUG */ 873 #ifndef HAVE_WCHAR 874 if (!(wlp->flags & __ISFORCED) && 875 (memcmp(nsp, csp, sizeof(__LDATA)) == 0)) { 876 if (wx <= lch) { 877 while (wx <= lch && 878 memcmp(nsp, csp, sizeof(__LDATA)) == 0) { 879 nsp++; 880 if (!_cursesi_screen->curwin) 881 ++csp; 882 ++wx; 883 } 884 continue; 885 } 886 break; 887 } 888 #else 889 #ifdef DEBUG 890 __CTRACE(__CTRACE_REFRESH, "makech: nsp=(%x,%x,%x,%x,%p)\n", 891 nsp->ch, nsp->attr, win->bch, win->battr, nsp->nsp); 892 __CTRACE(__CTRACE_REFRESH, "makech: csp=(%x,%x,%x,%x,%p)\n", 893 csp->ch, csp->attr, win->bch, win->battr, csp->nsp); 894 #endif /* DEBUG */ 895 if (!(wlp->flags & __ISFORCED) && 896 (((nsp->attr & __WCWIDTH) != __WCWIDTH) && 897 cellcmp(nsp, csp))) { 898 if (wx <= lch) { 899 while (wx <= lch && cellcmp( csp, nsp )) { 900 nsp++; 901 if (!_cursesi_screen->curwin) 902 ++csp; 903 ++wx; 904 } 905 continue; 906 } 907 break; 908 } 909 #endif /* HAVE_WCHAR */ 910 domvcur(_cursesi_screen->ly, _cursesi_screen->lx, wy, wx); 911 912 #ifdef DEBUG 913 __CTRACE(__CTRACE_REFRESH, "makech: 1: wx = %d, ly= %d, " 914 "lx = %d, newy = %d, newx = %d\n", 915 wx, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx); 916 #endif 917 _cursesi_screen->ly = wy; 918 _cursesi_screen->lx = wx; 919 #ifndef HAVE_WCHAR 920 while (wx <= lch && (memcmp(nsp, csp, sizeof(__LDATA)) != 0) || 921 (wlp->flags & __ISFORCED)) { 922 if (ce != NULL && 923 wx >= nlsp && nsp->ch == ' ' && nsp->attr == lspc) { 924 #else 925 while ((!cellcmp(nsp, csp) || (wlp->flags & __ISFORCED)) && 926 wx <= lch) { 927 if (ce != NULL && wx >= nlsp 928 && nsp->ch == (wchar_t)btowc((int)' ') /* XXX */ 929 && (nsp->attr & WA_ATTRIBUTES) == lspc) { 930 931 #endif 932 /* Check for clear to end-of-line. */ 933 cep = &curscr->alines[wy]->line[win->maxx - 1]; 934 #ifndef HAVE_WCHAR 935 while (cep->ch == ' ' && cep->attr == lspc) /* XXX */ 936 #else 937 while (cep->ch == (wchar_t)btowc((int)' ') 938 && (cep->attr & WA_ATTRIBUTES) == lspc) 939 #endif /* HAVE_WCHAR */ 940 if (cep-- <= csp) 941 break; 942 if (cep > (curscr->alines[wy]->line + win->begx * __LDATASIZE)) 943 clsp = cep - curscr->alines[wy]->line - 944 win->begx * __LDATASIZE; 945 else 946 clsp = 0; 947 #ifdef DEBUG 948 __CTRACE(__CTRACE_REFRESH, 949 "makech: clsp = %zu, nlsp = %zu\n", 950 clsp, nlsp); 951 __CTRACE(__CTRACE_REFRESH, 952 "makech: line = %p, cep = %p, begx = %u\n", 953 curscr->alines[wy]->line, cep, win->begx); 954 #endif 955 if (((clsp - nlsp >= strlen(clr_eol) && 956 clsp < win->maxx * __LDATASIZE) || 957 wy == win->maxy - 1) && 958 (!(lspc & __COLOR) || 959 ((lspc & __COLOR) && back_color_erase))) { 960 __unsetattr(0); 961 if (__using_color && 962 ((lspc & __COLOR) != 963 (curscr->wattr & __COLOR))) 964 __set_color(curscr, lspc & 965 __COLOR); 966 tputs(clr_eol, 0, __cputchar); 967 _cursesi_screen->lx = wx + win->begx; 968 while (wx++ <= clsp) { 969 csp->attr = lspc; 970 #ifndef HAVE_WCHAR 971 csp->ch = ' '; /* XXX */ 972 #else 973 csp->ch = (wchar_t)btowc((int)' '); 974 SET_WCOL( *csp, 1 ); 975 #endif /* HAVE_WCHAR */ 976 csp++; 977 } 978 return (OK); 979 } 980 ce = NULL; 981 } 982 983 #ifdef DEBUG 984 __CTRACE(__CTRACE_REFRESH, 985 "makech: have attr %08x, need attr %08x\n", 986 curscr->wattr 987 #ifndef HAVE_WCHAR 988 & __ATTRIBUTES 989 #else 990 & WA_ATTRIBUTES 991 #endif 992 , nsp->attr 993 #ifndef HAVE_WCHAR 994 & __ATTRIBUTES 995 #else 996 & WA_ATTRIBUTES 997 #endif 998 ); 999 #endif 1000 1001 off = (~nsp->attr & curscr->wattr) 1002 #ifndef HAVE_WCHAR 1003 & __ATTRIBUTES 1004 #else 1005 & WA_ATTRIBUTES 1006 #endif 1007 ; 1008 1009 /* 1010 * Unset attributes as appropriate. Unset first 1011 * so that the relevant attributes can be reset 1012 * (because 'me' unsets 'mb', 'md', 'mh', 'mk', 1013 * 'mp' and 'mr'). Check to see if we also turn off 1014 * standout, attributes and colour. 1015 */ 1016 if (off & __TERMATTR && exit_attribute_mode != NULL) { 1017 tputs(exit_attribute_mode, 0, __cputchar); 1018 curscr->wattr &= __mask_me; 1019 off &= __mask_me; 1020 } 1021 1022 /* 1023 * Exit underscore mode if appropriate. 1024 * Check to see if we also turn off standout, 1025 * attributes and colour. 1026 */ 1027 if (off & __UNDERSCORE && exit_underline_mode != NULL) { 1028 tputs(exit_underline_mode, 0, __cputchar); 1029 curscr->wattr &= __mask_ue; 1030 off &= __mask_ue; 1031 } 1032 1033 /* 1034 * Exit standout mode as appropriate. 1035 * Check to see if we also turn off underscore, 1036 * attributes and colour. 1037 * XXX 1038 * Should use uc if so/se not available. 1039 */ 1040 if (off & __STANDOUT && exit_standout_mode != NULL) { 1041 tputs(exit_standout_mode, 0, __cputchar); 1042 curscr->wattr &= __mask_se; 1043 off &= __mask_se; 1044 } 1045 1046 if (off & __ALTCHARSET && exit_alt_charset_mode != NULL) { 1047 tputs(exit_alt_charset_mode, 0, __cputchar); 1048 curscr->wattr &= ~__ALTCHARSET; 1049 } 1050 1051 /* Set/change colour as appropriate. */ 1052 if (__using_color) 1053 __set_color(curscr, nsp->attr & __COLOR); 1054 1055 on = (nsp->attr & ~curscr->wattr) 1056 #ifndef HAVE_WCHAR 1057 & __ATTRIBUTES 1058 #else 1059 & WA_ATTRIBUTES 1060 #endif 1061 ; 1062 1063 /* 1064 * Enter standout mode if appropriate. 1065 */ 1066 if (on & __STANDOUT && 1067 enter_standout_mode != NULL && 1068 exit_standout_mode != NULL) 1069 { 1070 tputs(enter_standout_mode, 0, __cputchar); 1071 curscr->wattr |= __STANDOUT; 1072 } 1073 1074 /* 1075 * Enter underscore mode if appropriate. 1076 * XXX 1077 * Should use uc if us/ue not available. 1078 */ 1079 if (on & __UNDERSCORE && 1080 enter_underline_mode != NULL && 1081 exit_underline_mode != NULL) 1082 { 1083 tputs(enter_underline_mode, 0, __cputchar); 1084 curscr->wattr |= __UNDERSCORE; 1085 } 1086 1087 /* 1088 * Set other attributes as appropriate. 1089 */ 1090 if (exit_attribute_mode != NULL) { 1091 if (on & __BLINK && 1092 enter_blink_mode != NULL) 1093 { 1094 tputs(enter_blink_mode, 0, __cputchar); 1095 curscr->wattr |= __BLINK; 1096 } 1097 if (on & __BOLD && 1098 enter_bold_mode != NULL) 1099 { 1100 tputs(enter_bold_mode, 0, __cputchar); 1101 curscr->wattr |= __BOLD; 1102 } 1103 if (on & __DIM && 1104 enter_dim_mode != NULL) 1105 { 1106 tputs(enter_dim_mode, 0, __cputchar); 1107 curscr->wattr |= __DIM; 1108 } 1109 if (on & __BLANK && 1110 enter_secure_mode != NULL) 1111 { 1112 tputs(enter_secure_mode, 0, __cputchar); 1113 curscr->wattr |= __BLANK; 1114 } 1115 if (on & __PROTECT && 1116 enter_protected_mode != NULL) 1117 { 1118 tputs(enter_protected_mode, 0, __cputchar); 1119 curscr->wattr |= __PROTECT; 1120 } 1121 if (on & __REVERSE && 1122 enter_reverse_mode != NULL) 1123 { 1124 tputs(enter_reverse_mode, 0, __cputchar); 1125 curscr->wattr |= __REVERSE; 1126 } 1127 #ifdef HAVE_WCHAR 1128 if (on & WA_TOP && 1129 enter_top_hl_mode != NULL) 1130 { 1131 tputs(enter_top_hl_mode, 0, __cputchar); 1132 curscr->wattr |= WA_TOP; 1133 } 1134 if (on & WA_LOW && 1135 enter_low_hl_mode != NULL) 1136 { 1137 tputs(enter_low_hl_mode, 0, __cputchar); 1138 curscr->wattr |= WA_LOW; 1139 } 1140 if (on & WA_LEFT && 1141 enter_left_hl_mode != NULL) 1142 { 1143 tputs(enter_left_hl_mode, 0, __cputchar); 1144 curscr->wattr |= WA_LEFT; 1145 } 1146 if (on & WA_RIGHT && 1147 enter_right_hl_mode != NULL) 1148 { 1149 tputs(enter_right_hl_mode, 0, __cputchar); 1150 curscr->wattr |= WA_RIGHT; 1151 } 1152 if (on & WA_HORIZONTAL && 1153 enter_horizontal_hl_mode != NULL) 1154 { 1155 tputs(enter_horizontal_hl_mode, 0, __cputchar); 1156 curscr->wattr |= WA_HORIZONTAL; 1157 } 1158 if (on & WA_VERTICAL && 1159 enter_vertical_hl_mode != NULL) 1160 { 1161 tputs(enter_vertical_hl_mode, 0, __cputchar); 1162 curscr->wattr |= WA_VERTICAL; 1163 } 1164 #endif /* HAVE_WCHAR */ 1165 } 1166 1167 /* Enter/exit altcharset mode as appropriate. */ 1168 if (on & __ALTCHARSET && enter_alt_charset_mode != NULL && 1169 exit_alt_charset_mode != NULL) { 1170 tputs(enter_alt_charset_mode, 0, __cputchar); 1171 curscr->wattr |= __ALTCHARSET; 1172 } 1173 1174 wx++; 1175 if (wx >= win->maxx && 1176 wy == win->maxy - 1 && !_cursesi_screen->curwin) { 1177 if (win->flags & __SCROLLOK) { 1178 if (win->flags & __ENDLINE) 1179 __unsetattr(1); 1180 if (!(win->flags & __SCROLLWIN)) { 1181 if (!_cursesi_screen->curwin) { 1182 csp->attr = nsp->attr; 1183 csp->ch = nsp->ch; 1184 #ifdef HAVE_WCHAR 1185 if (_cursesi_copy_nsp(nsp->nsp, csp) == ERR) 1186 return ERR; 1187 #endif /* HAVE_WCHAR */ 1188 } 1189 #ifndef HAVE_WCHAR 1190 __cputchar((int) nsp->ch); 1191 #else 1192 if ( WCOL( *nsp ) > 0 ) { 1193 __cputwchar((int)nsp->ch); 1194 #ifdef DEBUG 1195 __CTRACE(__CTRACE_REFRESH, 1196 "makech: (%d,%d)putwchar(0x%x)\n", 1197 wy, wx - 1, 1198 nsp->ch ); 1199 #endif /* DEBUG */ 1200 /* 1201 * Output non-spacing 1202 * characters for the 1203 * cell. 1204 */ 1205 __cursesi_putnsp(nsp->nsp, 1206 wy, wx); 1207 1208 } 1209 #endif /* HAVE_WCHAR */ 1210 } 1211 if (wx < curscr->maxx) { 1212 domvcur(_cursesi_screen->ly, wx, 1213 (int) (win->maxy - 1), 1214 (int) (win->maxx - 1)); 1215 } 1216 _cursesi_screen->ly = win->maxy - 1; 1217 _cursesi_screen->lx = win->maxx - 1; 1218 return (OK); 1219 } 1220 } 1221 if (wx < win->maxx || wy < win->maxy - 1 || 1222 !(win->flags & __SCROLLWIN)) { 1223 if (!_cursesi_screen->curwin) { 1224 csp->attr = nsp->attr; 1225 csp->ch = nsp->ch; 1226 #ifdef HAVE_WCHAR 1227 if (_cursesi_copy_nsp(nsp->nsp, 1228 csp) == ERR) 1229 return ERR; 1230 #endif /* HAVE_WCHAR */ 1231 csp++; 1232 } 1233 #ifndef HAVE_WCHAR 1234 __cputchar((int) nsp->ch); 1235 #ifdef DEBUG 1236 __CTRACE(__CTRACE_REFRESH, 1237 "makech: putchar(%c)\n", nsp->ch & 0177); 1238 #endif 1239 #else 1240 if (WCOL(*nsp) > 0) { 1241 __cputwchar((int) nsp->ch); 1242 #ifdef DEBUG 1243 __CTRACE(__CTRACE_REFRESH, 1244 "makech:(%d,%d) putwchar(%x)\n", 1245 wy, wx - 1, nsp->ch); 1246 __cursesi_putnsp(nsp->nsp, wy, wx); 1247 #endif /* DEBUG */ 1248 } 1249 #endif /* HAVE_WCHAR */ 1250 } 1251 if (underline_char && ((nsp->attr & __STANDOUT) || 1252 (nsp->attr & __UNDERSCORE))) { 1253 __cputchar('\b'); 1254 tputs(underline_char, 0, __cputchar); 1255 } 1256 nsp++; 1257 #ifdef DEBUG 1258 __CTRACE(__CTRACE_REFRESH, 1259 "makech: 2: wx = %d, lx = %d\n", 1260 wx, _cursesi_screen->lx); 1261 #endif 1262 } 1263 if (_cursesi_screen->lx == wx) /* If no change. */ 1264 break; 1265 _cursesi_screen->lx = wx; 1266 if (_cursesi_screen->lx >= COLS && auto_right_margin) 1267 _cursesi_screen->lx = COLS - 1; 1268 else 1269 if (wx >= win->maxx) { 1270 domvcur(_cursesi_screen->ly, 1271 _cursesi_screen->lx, 1272 _cursesi_screen->ly, 1273 (int) (win->maxx - 1)); 1274 _cursesi_screen->lx = win->maxx - 1; 1275 } 1276 #ifdef DEBUG 1277 __CTRACE(__CTRACE_REFRESH, "makech: 3: wx = %d, lx = %d\n", 1278 wx, _cursesi_screen->lx); 1279 #endif 1280 } 1281 #ifdef DEBUG 1282 #if HAVE_WCHAR 1283 { 1284 int x; 1285 __LDATA *lp, *vlp; 1286 1287 __CTRACE(__CTRACE_REFRESH, 1288 "makech-after: curscr(%p)-__virtscr(%p)\n", 1289 curscr, __virtscr ); 1290 for (x = 0; x < curscr->maxx; x++) { 1291 lp = &curscr->alines[wy]->line[x]; 1292 vlp = &__virtscr->alines[wy]->line[x]; 1293 __CTRACE(__CTRACE_REFRESH, 1294 "[%d,%d](%x,%x,%x,%x,%p)-" 1295 "(%x,%x,%x,%x,%p)\n", 1296 wy, x, lp->ch, lp->attr, 1297 win->bch, win->battr, lp->nsp, 1298 vlp->ch, vlp->attr, 1299 win->bch, win->battr, vlp->nsp); 1300 } 1301 } 1302 #endif /* HAVE_WCHAR */ 1303 #endif /* DEBUG */ 1304 1305 return (OK); 1306 } 1307 1308 /* 1309 * domvcur -- 1310 * Do a mvcur, leaving attributes if necessary. 1311 */ 1312 static void 1313 domvcur(oy, ox, ny, nx) 1314 int oy, ox, ny, nx; 1315 { 1316 #ifdef DEBUG 1317 __CTRACE(__CTRACE_REFRESH, "domvcur: (%x,%d)=>(%d,%d)\n", 1318 oy, ox, ny, nx ); 1319 #endif /* DEBUG */ 1320 __unsetattr(1); 1321 if ( oy == ny && ox == nx ) 1322 return; 1323 __mvcur(oy, ox, ny, nx, 1); 1324 } 1325 1326 /* 1327 * Quickch() attempts to detect a pattern in the change of the window 1328 * in order to optimize the change, e.g., scroll n lines as opposed to 1329 * repainting the screen line by line. 1330 */ 1331 1332 static __LDATA buf[128]; 1333 static u_int last_hash; 1334 static size_t last_hash_len; 1335 #define BLANKSIZE (sizeof(buf) / sizeof(buf[0])) 1336 1337 static void 1338 quickch(void) 1339 { 1340 #define THRESH (int) __virtscr->maxy / 4 1341 1342 __LINE *clp, *tmp1, *tmp2; 1343 int bsize, curs, curw, starts, startw, i, j; 1344 int n, target, cur_period, bot, top, sc_region; 1345 u_int blank_hash; 1346 attr_t bcolor; 1347 1348 #ifdef __GNUC__ 1349 curs = curw = starts = startw = 0; /* XXX gcc -Wuninitialized */ 1350 #endif 1351 /* 1352 * Find how many lines from the top of the screen are unchanged. 1353 */ 1354 for (top = 0; top < __virtscr->maxy; top++) 1355 #ifndef HAVE_WCHAR 1356 if (__virtscr->alines[top]->flags & __ISDIRTY && 1357 (__virtscr->alines[top]->hash != curscr->alines[top]->hash || 1358 memcmp(__virtscr->alines[top]->line, 1359 curscr->alines[top]->line, 1360 (size_t) __virtscr->maxx * __LDATASIZE) 1361 != 0)) 1362 break; 1363 #else 1364 if (__virtscr->alines[top]->flags & __ISDIRTY && 1365 (__virtscr->alines[top]->hash != curscr->alines[top]->hash || 1366 !linecmp(__virtscr->alines[top]->line, 1367 curscr->alines[top]->line, 1368 (size_t) __virtscr->maxx ))) 1369 break; 1370 #endif /* HAVE_WCHAR */ 1371 else 1372 __virtscr->alines[top]->flags &= ~__ISDIRTY; 1373 /* 1374 * Find how many lines from bottom of screen are unchanged. 1375 */ 1376 for (bot = __virtscr->maxy - 1; bot >= 0; bot--) 1377 #ifndef HAVE_WCHAR 1378 if (__virtscr->alines[bot]->flags & __ISDIRTY && 1379 (__virtscr->alines[bot]->hash != curscr->alines[bot]->hash || 1380 memcmp(__virtscr->alines[bot]->line, 1381 curscr->alines[bot]->line, 1382 (size_t) __virtscr->maxx * __LDATASIZE) 1383 != 0)) 1384 break; 1385 #else 1386 if (__virtscr->alines[bot]->flags & __ISDIRTY && 1387 (__virtscr->alines[bot]->hash != curscr->alines[bot]->hash || 1388 !linecmp(__virtscr->alines[bot]->line, 1389 curscr->alines[bot]->line, 1390 (size_t) __virtscr->maxx ))) 1391 break; 1392 #endif /* HAVE_WCHAR */ 1393 else 1394 __virtscr->alines[bot]->flags &= ~__ISDIRTY; 1395 1396 /* 1397 * Work round an xterm bug where inserting lines causes all the 1398 * inserted lines to be covered with the background colour we 1399 * set on the first line (even if we unset it for subsequent 1400 * lines). 1401 */ 1402 bcolor = __virtscr->alines[min(top, 1403 __virtscr->maxy - 1)]->line[0].attr & __COLOR; 1404 for (i = top + 1, j = 0; i < bot; i++) { 1405 if ((__virtscr->alines[i]->line[0].attr & __COLOR) != bcolor) { 1406 bcolor = __virtscr->alines[i]->line[__virtscr->maxx]. 1407 attr & __COLOR; 1408 j = i - top; 1409 } else 1410 break; 1411 } 1412 top += j; 1413 1414 #ifdef NO_JERKINESS 1415 /* 1416 * If we have a bottom unchanged region return. Scrolling the 1417 * bottom region up and then back down causes a screen jitter. 1418 * This will increase the number of characters sent to the screen 1419 * but it looks better. 1420 */ 1421 if (bot < __virtscr->maxy - 1) 1422 return; 1423 #endif /* NO_JERKINESS */ 1424 1425 /* 1426 * Search for the largest block of text not changed. 1427 * Invariants of the loop: 1428 * - Startw is the index of the beginning of the examined block in 1429 * __virtscr. 1430 * - Starts is the index of the beginning of the examined block in 1431 * curscr. 1432 * - Curw is the index of one past the end of the exmined block in 1433 * __virtscr. 1434 * - Curs is the index of one past the end of the exmined block in 1435 * curscr. 1436 * - bsize is the current size of the examined block. 1437 */ 1438 1439 for (bsize = bot - top; bsize >= THRESH; bsize--) { 1440 for (startw = top; startw <= bot - bsize; startw++) 1441 for (starts = top; starts <= bot - bsize; 1442 starts++) { 1443 for (curw = startw, curs = starts; 1444 curs < starts + bsize; curw++, curs++) 1445 if (__virtscr->alines[curw]->hash != 1446 curscr->alines[curs]->hash) 1447 break; 1448 if (curs != starts + bsize) 1449 continue; 1450 for (curw = startw, curs = starts; 1451 curs < starts + bsize; curw++, curs++) 1452 #ifndef HAVE_WCHAR 1453 if (memcmp(__virtscr->alines[curw]->line, 1454 curscr->alines[curs]->line, 1455 (size_t) __virtscr->maxx * 1456 __LDATASIZE) != 0) 1457 break; 1458 #else 1459 if (!linecmp(__virtscr->alines[curw]->line, 1460 curscr->alines[curs]->line, 1461 (size_t) __virtscr->maxx)) 1462 break; 1463 #endif /* HAVE_WCHAR */ 1464 if (curs == starts + bsize) 1465 goto done; 1466 } 1467 } 1468 done: 1469 1470 /* Did not find anything */ 1471 if (bsize < THRESH) 1472 return; 1473 1474 #ifdef DEBUG 1475 __CTRACE(__CTRACE_REFRESH, "quickch:bsize=%d, starts=%d, startw=%d, " 1476 "curw=%d, curs=%d, top=%d, bot=%d\n", 1477 bsize, starts, startw, curw, curs, top, bot); 1478 #endif 1479 1480 /* 1481 * Make sure that there is no overlap between the bottom and top 1482 * regions and the middle scrolled block. 1483 */ 1484 if (bot < curs) 1485 bot = curs - 1; 1486 if (top > starts) 1487 top = starts; 1488 1489 n = startw - starts; 1490 1491 #ifdef DEBUG 1492 __CTRACE(__CTRACE_REFRESH, "#####################################\n"); 1493 for (i = 0; i < curscr->maxy; i++) { 1494 __CTRACE(__CTRACE_REFRESH, "C: %d:", i); 1495 __CTRACE(__CTRACE_REFRESH, " 0x%x \n", curscr->alines[i]->hash); 1496 for (j = 0; j < curscr->maxx; j++) 1497 __CTRACE(__CTRACE_REFRESH, "%c", 1498 curscr->alines[i]->line[j].ch); 1499 __CTRACE(__CTRACE_REFRESH, "\n"); 1500 __CTRACE(__CTRACE_REFRESH, " attr:"); 1501 for (j = 0; j < curscr->maxx; j++) 1502 __CTRACE(__CTRACE_REFRESH, " %x", 1503 curscr->alines[i]->line[j].attr); 1504 __CTRACE(__CTRACE_REFRESH, "\n"); 1505 __CTRACE(__CTRACE_REFRESH, "W: %d:", i); 1506 __CTRACE(__CTRACE_REFRESH, " 0x%x \n", 1507 __virtscr->alines[i]->hash); 1508 __CTRACE(__CTRACE_REFRESH, " 0x%x ", 1509 __virtscr->alines[i]->flags); 1510 for (j = 0; j < __virtscr->maxx; j++) 1511 __CTRACE(__CTRACE_REFRESH, "%c", 1512 __virtscr->alines[i]->line[j].ch); 1513 __CTRACE(__CTRACE_REFRESH, "\n"); 1514 __CTRACE(__CTRACE_REFRESH, " attr:"); 1515 for (j = 0; j < __virtscr->maxx; j++) 1516 __CTRACE(__CTRACE_REFRESH, " %x", 1517 __virtscr->alines[i]->line[j].attr); 1518 __CTRACE(__CTRACE_REFRESH, "\n"); 1519 } 1520 #endif 1521 1522 #ifndef HAVE_WCHAR 1523 if (buf[0].ch != ' ') { 1524 for (i = 0; i < BLANKSIZE; i++) { 1525 buf[i].ch = ' '; 1526 buf[i].attr = 0; 1527 } 1528 } 1529 #else 1530 if (buf[0].ch != ( wchar_t )btowc(( int ) curscr->bch )) { 1531 for (i = 0; i < BLANKSIZE; i++) { 1532 buf[i].ch = ( wchar_t )btowc(( int ) curscr->bch ); 1533 if (_cursesi_copy_nsp(curscr->bnsp, &buf[i]) == ERR) 1534 return; 1535 buf[i].attr = 0; 1536 SET_WCOL( buf[ i ], 1 ); 1537 } 1538 } 1539 #endif /* HAVE_WCHAR */ 1540 1541 if (__virtscr->maxx != last_hash_len) { 1542 blank_hash = 0; 1543 for (i = __virtscr->maxx; i > BLANKSIZE; i -= BLANKSIZE) { 1544 blank_hash = __hash_more(buf, sizeof(buf), blank_hash); 1545 } 1546 blank_hash = __hash_more((char *)(void *)buf, 1547 i * sizeof(buf[0]), blank_hash); 1548 /* cache result in static data - screen width doesn't change often */ 1549 last_hash_len = __virtscr->maxx; 1550 last_hash = blank_hash; 1551 } else 1552 blank_hash = last_hash; 1553 1554 /* 1555 * Perform the rotation to maintain the consistency of curscr. 1556 * This is hairy since we are doing an *in place* rotation. 1557 * Invariants of the loop: 1558 * - I is the index of the current line. 1559 * - Target is the index of the target of line i. 1560 * - Tmp1 points to current line (i). 1561 * - Tmp2 and points to target line (target); 1562 * - Cur_period is the index of the end of the current period. 1563 * (see below). 1564 * 1565 * There are 2 major issues here that make this rotation non-trivial: 1566 * 1. Scrolling in a scrolling region bounded by the top 1567 * and bottom regions determined (whose size is sc_region). 1568 * 2. As a result of the use of the mod function, there may be a 1569 * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and 1570 * 0 to 2, which then causes all odd lines not to be rotated. 1571 * To remedy this, an index of the end ( = beginning) of the 1572 * current 'period' is kept, cur_period, and when it is reached, 1573 * the next period is started from cur_period + 1 which is 1574 * guaranteed not to have been reached since that would mean that 1575 * all records would have been reached. (think about it...). 1576 * 1577 * Lines in the rotation can have 3 attributes which are marked on the 1578 * line so that curscr is consistent with the visual screen. 1579 * 1. Not dirty -- lines inside the scrolled block, top region or 1580 * bottom region. 1581 * 2. Blank lines -- lines in the differential of the scrolling 1582 * region adjacent to top and bot regions 1583 * depending on scrolling direction. 1584 * 3. Dirty line -- all other lines are marked dirty. 1585 */ 1586 sc_region = bot - top + 1; 1587 i = top; 1588 tmp1 = curscr->alines[top]; 1589 cur_period = top; 1590 for (j = top; j <= bot; j++) { 1591 target = (i - top + n + sc_region) % sc_region + top; 1592 tmp2 = curscr->alines[target]; 1593 curscr->alines[target] = tmp1; 1594 /* Mark block as clean and blank out scrolled lines. */ 1595 clp = curscr->alines[target]; 1596 #ifdef DEBUG 1597 __CTRACE(__CTRACE_REFRESH, 1598 "quickch: n=%d startw=%d curw=%d i = %d target=%d ", 1599 n, startw, curw, i, target); 1600 #endif 1601 if ((target >= startw && target < curw) || target < top 1602 || target > bot) { 1603 #ifdef DEBUG 1604 __CTRACE(__CTRACE_REFRESH, " notdirty\n"); 1605 #endif 1606 __virtscr->alines[target]->flags &= ~__ISDIRTY; 1607 } else 1608 if ((n > 0 && target >= top && target < top + n) || 1609 (n < 0 && target <= bot && target > bot + n)) { 1610 #ifndef HAVE_WCHAR 1611 if (clp->hash != blank_hash || 1612 memcmp(clp->line, clp->line + 1, 1613 (__virtscr->maxx - 1) 1614 * __LDATASIZE) || 1615 memcmp(clp->line, buf, __LDATASIZE)) { 1616 #else 1617 if (clp->hash != blank_hash 1618 || linecmp(clp->line, clp->line + 1, 1619 (unsigned int) (__virtscr->maxx - 1)) 1620 || cellcmp(clp->line, buf)) { 1621 #endif /* HAVE_WCHAR */ 1622 for (i = __virtscr->maxx; 1623 i > BLANKSIZE; 1624 i -= BLANKSIZE) { 1625 (void) memcpy(clp->line + i - 1626 BLANKSIZE, buf, sizeof(buf)); 1627 } 1628 (void) memcpy(clp->line , buf, i * 1629 sizeof(buf[0])); 1630 #ifdef DEBUG 1631 __CTRACE(__CTRACE_REFRESH, 1632 " blanked out: dirty\n"); 1633 #endif 1634 clp->hash = blank_hash; 1635 __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1); 1636 } else { 1637 #ifdef DEBUG 1638 __CTRACE(__CTRACE_REFRESH, 1639 " -- blank line already: dirty\n"); 1640 #endif 1641 __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1); 1642 } 1643 } else { 1644 #ifdef DEBUG 1645 __CTRACE(__CTRACE_REFRESH, " -- dirty\n"); 1646 #endif 1647 __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1); 1648 } 1649 if (target == cur_period) { 1650 i = target + 1; 1651 tmp1 = curscr->alines[i]; 1652 cur_period = i; 1653 } else { 1654 tmp1 = tmp2; 1655 i = target; 1656 } 1657 } 1658 #ifdef DEBUG 1659 __CTRACE(__CTRACE_REFRESH, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); 1660 for (i = 0; i < curscr->maxy; i++) { 1661 __CTRACE(__CTRACE_REFRESH, "C: %d:", i); 1662 for (j = 0; j < curscr->maxx; j++) 1663 __CTRACE(__CTRACE_REFRESH, "%c", 1664 curscr->alines[i]->line[j].ch); 1665 __CTRACE(__CTRACE_REFRESH, "\n"); 1666 __CTRACE(__CTRACE_REFRESH, "W: %d:", i); 1667 for (j = 0; j < __virtscr->maxx; j++) 1668 __CTRACE(__CTRACE_REFRESH, "%c", 1669 __virtscr->alines[i]->line[j].ch); 1670 __CTRACE(__CTRACE_REFRESH, "\n"); 1671 } 1672 #endif 1673 if (n != 0) 1674 scrolln(starts, startw, curs, bot, top); 1675 } 1676 1677 /* 1678 * scrolln -- 1679 * Scroll n lines, where n is starts - startw. 1680 */ 1681 static void /* ARGSUSED */ 1682 scrolln(starts, startw, curs, bot, top) 1683 int starts, startw, curs, bot, top; 1684 { 1685 int i, oy, ox, n; 1686 1687 oy = curscr->cury; 1688 ox = curscr->curx; 1689 n = starts - startw; 1690 1691 /* 1692 * XXX 1693 * The initial tests that set __noqch don't let us reach here unless 1694 * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr 1695 * scrolling can only shift the entire scrolling region, not just a 1696 * part of it, which means that the quickch() routine is going to be 1697 * sadly disappointed in us if we don't have cs as well. 1698 * 1699 * If cs, ho and SF/sf are set, can use the scrolling region. Because 1700 * the cursor position after cs is undefined, we need ho which gives us 1701 * the ability to move to somewhere without knowledge of the current 1702 * location of the cursor. Still call __mvcur() anyway, to update its 1703 * idea of where the cursor is. 1704 * 1705 * When the scrolling region has been set, the cursor has to be at the 1706 * last line of the region to make the scroll happen. 1707 * 1708 * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr 1709 * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not 1710 * SF/SR. So, if we're scrolling almost all of the screen, try and use 1711 * AL/DL, otherwise use the scrolling region. The "almost all" is a 1712 * shameless hack for vi. 1713 */ 1714 if (n > 0) { 1715 if (change_scroll_region != NULL && cursor_home != NULL && 1716 (parm_index != NULL || 1717 ((parm_insert_line == NULL || parm_delete_line == NULL || 1718 top > 3 || bot + 3 < __virtscr->maxy) && 1719 scroll_forward != NULL))) 1720 { 1721 tputs(tiparm(change_scroll_region, top, bot), 1722 0, __cputchar); 1723 __mvcur(oy, ox, 0, 0, 1); 1724 tputs(cursor_home, 0, __cputchar); 1725 __mvcur(0, 0, bot, 0, 1); 1726 if (parm_index != NULL) 1727 tputs(tiparm(parm_index, n), 1728 0, __cputchar); 1729 else 1730 for (i = 0; i < n; i++) 1731 tputs(scroll_forward, 0, __cputchar); 1732 tputs(tiparm(change_scroll_region, 1733 0, (int) __virtscr->maxy - 1), 0, __cputchar); 1734 __mvcur(bot, 0, 0, 0, 1); 1735 tputs(cursor_home, 0, __cputchar); 1736 __mvcur(0, 0, oy, ox, 1); 1737 return; 1738 } 1739 1740 /* Scroll up the block. */ 1741 if (parm_index != NULL && top == 0) { 1742 __mvcur(oy, ox, bot, 0, 1); 1743 tputs(tiparm(parm_index, n), 0, __cputchar); 1744 } else 1745 if (parm_delete_line != NULL) { 1746 __mvcur(oy, ox, top, 0, 1); 1747 tputs(tiparm(parm_delete_line, n), 1748 0, __cputchar); 1749 } else 1750 if (delete_line != NULL) { 1751 __mvcur(oy, ox, top, 0, 1); 1752 for (i = 0; i < n; i++) 1753 tputs(delete_line, 1754 0, __cputchar); 1755 } else 1756 if (scroll_forward != NULL && top == 0) { 1757 __mvcur(oy, ox, bot, 0, 1); 1758 for (i = 0; i < n; i++) 1759 tputs(scroll_forward, 0, 1760 __cputchar); 1761 } else 1762 abort(); 1763 1764 /* Push down the bottom region. */ 1765 __mvcur(top, 0, bot - n + 1, 0, 1); 1766 if (parm_insert_line != NULL) 1767 tputs(tiparm(parm_insert_line, n), 0, __cputchar); 1768 else 1769 if (insert_line != NULL) 1770 for (i = 0; i < n; i++) 1771 tputs(insert_line, 0, __cputchar); 1772 else 1773 abort(); 1774 __mvcur(bot - n + 1, 0, oy, ox, 1); 1775 } else { 1776 /* 1777 * !!! 1778 * n < 0 1779 * 1780 * If cs, ho and SR/sr are set, can use the scrolling region. 1781 * See the above comments for details. 1782 */ 1783 if (change_scroll_region != NULL && cursor_home != NULL && 1784 (parm_rindex != NULL || 1785 ((parm_insert_line == NULL || parm_delete_line == NULL || 1786 top > 3 || 1787 bot + 3 < __virtscr->maxy) && scroll_reverse != NULL))) 1788 { 1789 tputs(tiparm(change_scroll_region, top, bot), 1790 0, __cputchar); 1791 __mvcur(oy, ox, 0, 0, 1); 1792 tputs(cursor_home, 0, __cputchar); 1793 __mvcur(0, 0, top, 0, 1); 1794 1795 if (parm_rindex != NULL) 1796 tputs(tiparm(parm_rindex, -n), 1797 0, __cputchar); 1798 else 1799 for (i = n; i < 0; i++) 1800 tputs(scroll_reverse, 0, __cputchar); 1801 tputs(tiparm(change_scroll_region, 1802 0, (int) __virtscr->maxy - 1), 0, __cputchar); 1803 __mvcur(top, 0, 0, 0, 1); 1804 tputs(cursor_home, 0, __cputchar); 1805 __mvcur(0, 0, oy, ox, 1); 1806 return; 1807 } 1808 1809 /* Preserve the bottom lines. */ 1810 __mvcur(oy, ox, bot + n + 1, 0, 1); 1811 if (parm_rindex != NULL && bot == __virtscr->maxy) 1812 tputs(tiparm(parm_rindex, -n), 0, __cputchar); 1813 else 1814 if (parm_delete_line != NULL) 1815 tputs(tiparm(parm_delete_line, -n), 1816 0, __cputchar); 1817 else 1818 if (delete_line != NULL) 1819 for (i = n; i < 0; i++) 1820 tputs(delete_line, 1821 0, __cputchar); 1822 else 1823 if (scroll_reverse != NULL && 1824 bot == __virtscr->maxy) 1825 for (i = n; i < 0; i++) 1826 tputs(scroll_reverse, 0, 1827 __cputchar); 1828 else 1829 abort(); 1830 1831 /* Scroll the block down. */ 1832 __mvcur(bot + n + 1, 0, top, 0, 1); 1833 if (parm_insert_line != NULL) 1834 tputs(tiparm(parm_insert_line, -n), 0, __cputchar); 1835 else 1836 if (insert_line != NULL) 1837 for (i = n; i < 0; i++) 1838 tputs(insert_line, 0, __cputchar); 1839 else 1840 abort(); 1841 __mvcur(top, 0, oy, ox, 1); 1842 } 1843 } 1844 1845 /* 1846 * __unsetattr -- 1847 * Unset attributes on curscr. Leave standout, attribute and colour 1848 * modes if necessary (!ms). Always leave altcharset (xterm at least 1849 * ignores a cursor move if we don't). 1850 */ 1851 void /* ARGSUSED */ 1852 __unsetattr(int checkms) 1853 { 1854 int isms; 1855 1856 if (checkms) 1857 if (!move_standout_mode) { 1858 isms = 1; 1859 } else { 1860 isms = 0; 1861 } 1862 else 1863 isms = 1; 1864 #ifdef DEBUG 1865 __CTRACE(__CTRACE_REFRESH, 1866 "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n", 1867 checkms, move_standout_mode ? "TRUE" : "FALSE", curscr->wattr); 1868 #endif 1869 1870 /* 1871 * Don't leave the screen in standout mode (check against ms). Check 1872 * to see if we also turn off underscore, attributes and colour. 1873 */ 1874 if (curscr->wattr & __STANDOUT && isms) { 1875 tputs(exit_standout_mode, 0, __cputchar); 1876 curscr->wattr &= __mask_se; 1877 } 1878 /* 1879 * Don't leave the screen in underscore mode (check against ms). 1880 * Check to see if we also turn off attributes. Assume that we 1881 * also turn off colour. 1882 */ 1883 if (curscr->wattr & __UNDERSCORE && isms) { 1884 tputs(exit_underline_mode, 0, __cputchar); 1885 curscr->wattr &= __mask_ue; 1886 } 1887 /* 1888 * Don't leave the screen with attributes set (check against ms). 1889 * Assume that also turn off colour. 1890 */ 1891 if (curscr->wattr & __TERMATTR && isms) { 1892 tputs(exit_attribute_mode, 0, __cputchar); 1893 curscr->wattr &= __mask_me; 1894 } 1895 /* Don't leave the screen with altcharset set (don't check ms). */ 1896 if (curscr->wattr & __ALTCHARSET) { 1897 tputs(exit_alt_charset_mode, 0, __cputchar); 1898 curscr->wattr &= ~__ALTCHARSET; 1899 } 1900 /* Don't leave the screen with colour set (check against ms). */ 1901 if (__using_color && isms) 1902 __unset_color(curscr); 1903 } 1904 1905 #ifdef HAVE_WCHAR 1906 /* compare two cells on screen, must have the same forground/background, 1907 * and the same sequence of non-spacing characters */ 1908 int 1909 cellcmp( __LDATA *x, __LDATA *y ) 1910 { 1911 nschar_t *xnp = x->nsp, *ynp = y->nsp; 1912 int ret = ( x->ch == y->ch ) & ( x->attr == y->attr ); 1913 1914 if ( !ret ) 1915 return 0; 1916 if ( !xnp && !ynp ) 1917 return 1; 1918 if (( xnp && !ynp ) || ( !xnp && ynp )) 1919 return 0; 1920 1921 while ( xnp && ynp ) { 1922 if ( xnp->ch != ynp->ch ) 1923 return 0; 1924 xnp = xnp->next; 1925 ynp = ynp->next; 1926 } 1927 return ( !xnp && !ynp ); 1928 } 1929 1930 /* compare two line segments */ 1931 int 1932 linecmp( __LDATA *xl, __LDATA *yl, size_t len ) 1933 { 1934 int i = 0; 1935 __LDATA *xp = xl, *yp = yl; 1936 1937 for ( i = 0; i < len; i++, xp++, yp++ ) { 1938 if ( !cellcmp( xp, yp )) 1939 return 0; 1940 } 1941 return 1; 1942 } 1943 1944 /* 1945 * Output the non-spacing characters associated with the given character 1946 * cell to the screen. 1947 */ 1948 1949 void 1950 __cursesi_putnsp(nschar_t *nsp, const int wy, const int wx) 1951 { 1952 nschar_t *p; 1953 1954 /* this shuts up gcc warnings about wx and wy not being used */ 1955 if (wx > wy) { 1956 } 1957 1958 p = nsp; 1959 while (p != NULL) { 1960 __cputwchar((int) p->ch); 1961 #ifdef DEBUG 1962 __CTRACE(__CTRACE_REFRESH, 1963 "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n", 1964 wy, wx - 1, p->ch); 1965 #endif 1966 p = p->next; 1967 } 1968 } 1969 1970 #endif /* HAVE_WCHAR */ 1971