1 /* $NetBSD: refresh.c,v 1.70 2008/06/13 03:18:04 yamt Exp $ */
4 * Copyright (c) 1981, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94";
37 __RCSID("$NetBSD: refresh.c,v 1.70 2008/06/13 03:18:04 yamt Exp $");
45 #include "curses_private.h"
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);
52 static int _cursesi_wnoutrefresh(SCREEN
*, WINDOW
*,
53 int, int, int, int, int, int);
56 int cellcmp( __LDATA
*, __LDATA
* );
57 int linecmp( __LDATA
*, __LDATA
*, size_t );
58 #endif /* HAVE_WCHAR */
60 #ifndef _CURSES_USE_MACROS
64 * Make the current screen look like "stdscr" over the area covered by
70 return wrefresh(stdscr
);
77 * Add the contents of "win" to the virtual window.
80 wnoutrefresh(WINDOW
*win
)
83 __CTRACE(__CTRACE_REFRESH
, "wnoutrefresh: win %p\n", win
);
86 return _cursesi_wnoutrefresh(_cursesi_screen
, win
, 0, 0, win
->begy
,
87 win
->begx
, win
->maxy
, win
->maxx
);
92 * Add the contents of "pad" to the virtual window.
95 pnoutrefresh(WINDOW
*pad
, int pbegy
, int pbegx
, int sbegy
, int sbegx
,
101 __CTRACE(__CTRACE_REFRESH
, "pnoutrefresh: pad %p, flags 0x%08x\n",
103 __CTRACE(__CTRACE_REFRESH
,
104 "pnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n",
105 pbegy
, pbegx
, sbegy
, sbegx
, smaxy
, smaxx
);
108 /* SUS says if these are negative, they should be treated as zero */
118 /* Calculate rectangle on pad - used by _cursesi_wnoutrefresh */
119 pmaxy
= pbegy
+ smaxy
- sbegy
+ 1;
120 pmaxx
= pbegx
+ smaxx
- sbegx
+ 1;
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
;
128 if (smaxy
- sbegy
< 0 || smaxx
- sbegx
< 0 )
131 return _cursesi_wnoutrefresh(_cursesi_screen
, pad
,
132 pad
->begy
+ pbegy
, pad
->begx
+ pbegx
, pad
->begy
+ sbegy
,
133 pad
->begx
+ sbegx
, pmaxy
, pmaxx
);
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).
143 _cursesi_wnoutrefresh(SCREEN
*screen
, WINDOW
*win
, int begy
, int begx
,
144 int wbegy
, int wbegx
, int maxy
, int maxx
)
147 short sy
, wy
, wx
, y_off
, x_off
, mx
;
149 WINDOW
*sub_win
, *orig
;
152 __CTRACE(__CTRACE_REFRESH
, "_wnoutrefresh: win %p, flags 0x%08x\n",
154 __CTRACE(__CTRACE_REFRESH
,
155 "_wnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n",
156 begy
, begx
, wbegy
, wbegx
, maxy
, maxx
);
163 * Recurse through any sub-windows, mark as dirty lines on the parent
164 * window that are dirty on the sub-window and clear the dirty flag on
167 if (win
->orig
== 0) {
169 for (sub_win
= win
->nextp
; sub_win
!= win
;
170 sub_win
= sub_win
->nextp
) {
172 __CTRACE(__CTRACE_REFRESH
,
173 "wnout_refresh: win %p, sub_win %p\n",
176 for (sy
= 0; sy
< sub_win
->maxy
; sy
++) {
177 if (sub_win
->alines
[sy
]->flags
== __ISDIRTY
) {
178 orig
->alines
[sy
+ sub_win
->begy
- orig
->begy
]->flags
180 sub_win
->alines
[sy
]->flags
187 /* Check that cursor position on "win" is valid for "__virtscr" */
188 if (win
->cury
+ wbegy
- begy
< screen
->__virtscr
->maxy
&&
189 win
->cury
+ wbegy
- begy
>= 0 && win
->cury
< maxy
- begy
)
190 screen
->__virtscr
->cury
= win
->cury
+ wbegy
- begy
;
191 if (win
->curx
+ wbegx
- begx
< screen
->__virtscr
->maxx
&&
192 win
->curx
+ wbegx
- begx
>= 0 && win
->curx
< maxx
- begx
)
193 screen
->__virtscr
->curx
= win
->curx
+ wbegx
- begx
;
195 /* Copy the window flags from "win" to "__virtscr" */
196 if (win
->flags
& __CLEAROK
) {
197 if (win
->flags
& __FULLWIN
)
198 screen
->__virtscr
->flags
|= __CLEAROK
;
199 win
->flags
&= ~__CLEAROK
;
201 screen
->__virtscr
->flags
&= ~__LEAVEOK
;
202 screen
->__virtscr
->flags
|= win
->flags
;
204 for (wy
= begy
, y_off
= wbegy
; wy
< maxy
&&
205 y_off
< screen
->__virtscr
->maxy
; wy
++, y_off
++) {
206 wlp
= win
->alines
[wy
];
208 __CTRACE(__CTRACE_REFRESH
,
209 "_wnoutrefresh: wy %d\tf %d\tl %d\tflags %x\n",
210 wy
, *wlp
->firstchp
, *wlp
->lastchp
, wlp
->flags
);
212 if ((wlp
->flags
& __ISDIRTY
) == 0)
214 vlp
= screen
->__virtscr
->alines
[y_off
];
216 if (*wlp
->firstchp
< maxx
+ win
->ch_off
&&
217 *wlp
->lastchp
>= win
->ch_off
) {
218 /* Set start column */
221 if (*wlp
->firstchp
- win
->ch_off
> 0) {
222 wx
+= *wlp
->firstchp
- win
->ch_off
;
223 x_off
+= *wlp
->firstchp
- win
->ch_off
;
225 /* Set finish column */
227 if (mx
> *wlp
->lastchp
- win
->ch_off
+ 1)
228 mx
= *wlp
->lastchp
- win
->ch_off
+ 1;
229 if (x_off
+ (mx
- wx
) > __virtscr
->maxx
)
230 mx
-= (x_off
+ maxx
) - __virtscr
->maxx
;
231 /* Copy line from "win" to "__virtscr". */
234 __CTRACE(__CTRACE_REFRESH
,
235 "_wnoutrefresh: copy from %d, "
237 wy
, wx
, y_off
, x_off
);
240 vlp
->line
[x_off
].ch
= wlp
->line
[wx
].ch
;
241 /* Copy attributes */
242 vlp
->line
[x_off
].attr
= wlp
->line
[wx
].attr
;
243 /* Check for nca conflict with colour */
244 if ((vlp
->line
[x_off
].attr
& __COLOR
) &&
245 (vlp
->line
[x_off
].attr
&
246 _cursesi_screen
->nca
))
247 vlp
->line
[x_off
].attr
&= ~__COLOR
;
250 == (wchar_t)btowc((int) win
->bch
)) {
251 vlp
->line
[x_off
].ch
= win
->bch
;
252 SET_WCOL( vlp
->line
[x_off
], 1 );
253 if (_cursesi_copy_nsp(win
->bnsp
,
258 #endif /* HAVE_WCHAR */
263 /* Set flags on "__virtscr" and unset on "win". */
264 if (wlp
->flags
& __ISPASTEOL
)
265 vlp
->flags
|= __ISPASTEOL
;
267 vlp
->flags
&= ~__ISPASTEOL
;
268 if (wlp
->flags
& __ISDIRTY
)
269 vlp
->flags
|= __ISDIRTY
;
272 __CTRACE(__CTRACE_REFRESH
,
273 "win: firstch = %d, lastch = %d\n",
274 *wlp
->firstchp
, *wlp
->lastchp
);
276 /* Set change pointers on "__virtscr". */
278 *wlp
->firstchp
+ wbegx
- win
->ch_off
)
280 *wlp
->firstchp
+ wbegx
- win
->ch_off
;
282 *wlp
->lastchp
+ wbegx
- win
->ch_off
)
284 *wlp
->lastchp
+ wbegx
- win
->ch_off
;
286 __CTRACE(__CTRACE_REFRESH
,
287 "__virtscr: firstch = %d, lastch = %d\n",
288 *vlp
->firstchp
, *vlp
->lastchp
);
291 * Unset change pointers only if a window, as a pad
292 * can be displayed again without any of the contents
295 if (!(win
->flags
& __ISPAD
)) {
296 /* Set change pointers on "win". */
297 if (*wlp
->firstchp
>= win
->ch_off
)
298 *wlp
->firstchp
= maxx
+ win
->ch_off
;
299 if (*wlp
->lastchp
< maxx
+ win
->ch_off
)
300 *wlp
->lastchp
= win
->ch_off
;
301 if ((*wlp
->lastchp
< *wlp
->firstchp
) ||
302 (*wlp
->firstchp
>= maxx
+ win
->ch_off
) ||
303 (*wlp
->lastchp
<= win
->ch_off
)) {
305 __CTRACE(__CTRACE_REFRESH
,
307 "line %d notdirty\n", wy
);
309 wlp
->flags
&= ~__ISDIRTY
;
319 * Make the current screen look like "win" over the area covered by
323 wrefresh(WINDOW
*win
)
328 __CTRACE(__CTRACE_REFRESH
, "wrefresh: win %p\n", win
);
331 _cursesi_screen
->curwin
= (win
== _cursesi_screen
->curscr
);
332 if (!_cursesi_screen
->curwin
)
333 retval
= _cursesi_wnoutrefresh(_cursesi_screen
, win
, 0, 0,
334 win
->begy
, win
->begx
, win
->maxy
, win
->maxx
);
339 if (!(win
->flags
& __LEAVEOK
)) {
340 win
->cury
= max(0, curscr
->cury
- win
->begy
);
341 win
->curx
= max(0, curscr
->curx
- win
->begx
);
344 _cursesi_screen
->curwin
= 0;
350 * Make the current screen look like "pad" over the area coverd by
351 * the specified area of pad.
354 prefresh(WINDOW
*pad
, int pbegy
, int pbegx
, int sbegy
, int sbegx
,
355 int smaxy
, int smaxx
)
360 __CTRACE(__CTRACE_REFRESH
, "prefresh: pad %p, flags 0x%08x\n",
363 /* Retain values in case pechochar() is called. */
371 /* Use pnoutrefresh() to avoid duplicating code here */
372 retval
= pnoutrefresh(pad
, pbegy
, pbegx
, sbegy
, sbegx
, smaxy
, smaxx
);
375 if (!(pad
->flags
& __LEAVEOK
)) {
376 pad
->cury
= max(0, curscr
->cury
- pad
->begy
);
377 pad
->curx
= max(0, curscr
->curx
- pad
->begx
);
385 * Make the current screen look like the virtual window "__virtscr".
398 #endif /* HAVE_WCHAR */
400 /* Check if we need to restart ... */
401 if (_cursesi_screen
->endwin
)
404 if (_cursesi_screen
->curwin
)
407 win
= _cursesi_screen
->__virtscr
;
409 /* Initialize loop parameters. */
410 _cursesi_screen
->ly
= curscr
->cury
;
411 _cursesi_screen
->lx
= curscr
->curx
;
414 if (!_cursesi_screen
->curwin
) {
415 for (wy
= 0; wy
< win
->maxy
; wy
++) {
416 wlp
= win
->alines
[wy
];
417 if (wlp
->flags
& __ISDIRTY
) {
419 wlp
->hash
= __hash(wlp
->line
,
420 (size_t)(win
->maxx
* __LDATASIZE
));
423 for ( x
= 0; x
< win
->maxx
; x
++ ) {
424 lp
= &wlp
->line
[ x
];
425 wlp
->hash
= __hash_more( &lp
->ch
,
426 sizeof( wchar_t ), wlp
->hash
);
427 wlp
->hash
= __hash_more( &lp
->attr
,
428 sizeof( attr_t
), wlp
->hash
);
441 #endif /* HAVE_WCHAR */
446 if ((win
->flags
& __CLEAROK
) || (curscr
->flags
& __CLEAROK
) ||
447 _cursesi_screen
->curwin
) {
448 if (curscr
->wattr
& __COLOR
)
450 tputs(__tc_cl
, 0, __cputchar
);
451 _cursesi_screen
->ly
= 0;
452 _cursesi_screen
->lx
= 0;
453 if (!_cursesi_screen
->curwin
) {
454 curscr
->flags
&= ~__CLEAROK
;
460 win
->flags
&= ~__CLEAROK
;
465 if (!_cursesi_screen
->curwin
)
469 __CTRACE(__CTRACE_REFRESH
, "doupdate: (%p): curwin = %d\n", win
,
470 _cursesi_screen
->curwin
);
471 __CTRACE(__CTRACE_REFRESH
, "doupdate: \tfirstch\tlastch\n");
474 if (!_cursesi_screen
->curwin
) {
476 * Invoke quickch() only if more than a quarter of the lines
477 * in the window are dirty.
479 for (wy
= 0, dnum
= 0; wy
< win
->maxy
; wy
++)
480 if (win
->alines
[wy
]->flags
& __ISDIRTY
)
482 if (!__noqch
&& dnum
> (int) win
->maxy
/ 4)
490 __CTRACE(__CTRACE_REFRESH
,
491 "#####################################\n");
492 __CTRACE(__CTRACE_REFRESH
,
493 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
494 stdscr
, curscr
, _cursesi_screen
->__virtscr
);
495 for (i
= 0; i
< curscr
->maxy
; i
++) {
496 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
497 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
498 curscr
->alines
[i
]->hash
);
499 for (j
= 0; j
< curscr
->maxx
; j
++)
500 __CTRACE(__CTRACE_REFRESH
, "%c",
501 curscr
->alines
[i
]->line
[j
].ch
);
502 __CTRACE(__CTRACE_REFRESH
, "\n");
503 __CTRACE(__CTRACE_REFRESH
, " attr:");
504 for (j
= 0; j
< curscr
->maxx
; j
++)
505 __CTRACE(__CTRACE_REFRESH
, " %x",
506 curscr
->alines
[i
]->line
[j
].attr
);
507 __CTRACE(__CTRACE_REFRESH
, "\n");
508 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
509 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
510 win
->alines
[i
]->hash
);
511 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
512 win
->alines
[i
]->flags
);
513 for (j
= 0; j
< win
->maxx
; j
++)
514 __CTRACE(__CTRACE_REFRESH
, "%c",
515 win
->alines
[i
]->line
[j
].ch
);
516 __CTRACE(__CTRACE_REFRESH
, "\n");
517 __CTRACE(__CTRACE_REFRESH
, " attr:");
518 for (j
= 0; j
< win
->maxx
; j
++)
519 __CTRACE(__CTRACE_REFRESH
, " %x",
520 win
->alines
[i
]->line
[j
].attr
);
521 __CTRACE(__CTRACE_REFRESH
, "\n");
523 __CTRACE(__CTRACE_REFRESH
, " nsp:");
524 for (j
= 0; j
< curscr
->maxx
; j
++)
525 __CTRACE(__CTRACE_REFRESH
, " %p",
526 win
->alines
[i
]->line
[j
].nsp
);
527 __CTRACE(__CTRACE_REFRESH
, "\n");
528 __CTRACE(__CTRACE_REFRESH
, " bnsp:");
529 for (j
= 0; j
< curscr
->maxx
; j
++)
530 __CTRACE(__CTRACE_REFRESH
, " %p",
532 __CTRACE(__CTRACE_REFRESH
, "\n");
533 #endif /* HAVE_WCHAR */
538 for (wy
= 0; wy
< win
->maxy
; wy
++) {
539 wlp
= win
->alines
[wy
];
540 /* XXX: remove this debug */
542 __CTRACE(__CTRACE_REFRESH
,
543 "doupdate: wy %d\tf: %d\tl:%d\tflags %x\n",
544 wy
, *wlp
->firstchp
, *wlp
->lastchp
, wlp
->flags
);
546 if (!_cursesi_screen
->curwin
)
547 curscr
->alines
[wy
]->hash
= wlp
->hash
;
548 if (wlp
->flags
& __ISDIRTY
) {
550 __CTRACE(__CTRACE_REFRESH
,
551 "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy
,
552 *wlp
->firstchp
, *wlp
->lastchp
);
554 if (makech(wy
) == ERR
)
557 if (*wlp
->firstchp
>= 0)
558 *wlp
->firstchp
= win
->maxx
;
559 if (*wlp
->lastchp
< win
->maxx
)
561 if (*wlp
->lastchp
< *wlp
->firstchp
) {
563 __CTRACE(__CTRACE_REFRESH
,
564 "doupdate: line %d notdirty\n", wy
);
566 wlp
->flags
&= ~__ISDIRTY
;
572 __CTRACE(__CTRACE_REFRESH
, "\t%d\t%d\n",
573 *wlp
->firstchp
, *wlp
->lastchp
);
578 __CTRACE(__CTRACE_REFRESH
, "doupdate: ly=%d, lx=%d\n",
579 _cursesi_screen
->ly
, _cursesi_screen
->lx
);
582 if (_cursesi_screen
->curwin
)
583 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
584 win
->cury
, win
->curx
);
586 if (win
->flags
& __LEAVEOK
) {
587 curscr
->cury
= _cursesi_screen
->ly
;
588 curscr
->curx
= _cursesi_screen
->lx
;
590 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
591 win
->cury
, win
->curx
);
592 curscr
->cury
= win
->cury
;
593 curscr
->curx
= win
->curx
;
597 /* Don't leave the screen with attributes set. */
604 __CTRACE(__CTRACE_REFRESH
,
605 "***********after*****************\n");
606 __CTRACE(__CTRACE_REFRESH
,
607 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
608 stdscr
, curscr
, _cursesi_screen
->__virtscr
);
609 for (i
= 0; i
< curscr
->maxy
; i
++) {
610 for (j
= 0; j
< curscr
->maxx
; j
++)
611 __CTRACE(__CTRACE_REFRESH
,
612 "[%d,%d](%x,%x,%p)-(%x,%x,%p)\n",
614 curscr
->alines
[i
]->line
[j
].ch
,
615 curscr
->alines
[i
]->line
[j
].attr
,
616 curscr
->alines
[i
]->line
[j
].nsp
,
617 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].ch
,
618 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].attr
,
619 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].nsp
);
622 #endif /* HAVE_WCHAR */
624 return fflush(_cursesi_screen
->outfd
) == EOF
? ERR
: OK
;
629 * Make a change on the screen.
635 static __LDATA blank
;
636 __LDATA
*nsp
, *csp
, *cp
, *cep
;
637 size_t clsp
, nlsp
; /* Last space in lines. */
640 attr_t lspc
; /* Last space colour */
644 nlsp
= lspc
= 0; /* XXX gcc -Wuninitialized */
646 if (_cursesi_screen
->curwin
)
651 blank
.ch
= ( wchar_t )btowc(( int ) win
->bch
);
653 if (_cursesi_copy_nsp(win
->bnsp
, &blank
) == ERR
)
655 SET_WCOL( blank
, 1 );
656 #endif /* HAVE_WCHAR */
663 __CTRACE(__CTRACE_REFRESH
,
664 "[makech-before]wy=%d,curscr(%p)-__virtscr(%p)\n",
665 wy
, curscr
, __virtscr
);
666 for (x
= 0; x
< curscr
->maxx
; x
++) {
667 lp
= &curscr
->alines
[wy
]->line
[x
];
668 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
669 __CTRACE(__CTRACE_REFRESH
,
670 "[%d,%d](%x,%x,%x,%x,%p)-"
671 "(%x,%x,%x,%x,%p)\n",
672 wy
, x
, lp
->ch
, lp
->attr
,
673 win
->bch
, win
->battr
, lp
->nsp
,
675 win
->bch
, win
->battr
, vlp
->nsp
);
678 #endif /* HAVE_WCHAR */
680 /* Is the cursor still on the end of the last line? */
681 if (wy
> 0 && curscr
->alines
[wy
- 1]->flags
& __ISPASTEOL
) {
682 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
683 _cursesi_screen
->ly
+ 1, 0);
684 _cursesi_screen
->ly
++;
685 _cursesi_screen
->lx
= 0;
687 wx
= *win
->alines
[wy
]->firstchp
;
693 lch
= *win
->alines
[wy
]->lastchp
;
697 if (lch
>= (int) win
->maxx
)
700 if (_cursesi_screen
->curwin
) {
703 __CTRACE(__CTRACE_REFRESH
, "makech: csp is blank\n");
706 csp
= &curscr
->alines
[wy
]->line
[wx
];
708 __CTRACE(__CTRACE_REFRESH
,
709 "makech: csp is on curscr:(%d,%d)\n", wy
, wx
);
713 nsp
= &win
->alines
[wy
]->line
[wx
];
715 if ( _cursesi_screen
->curwin
)
716 __CTRACE(__CTRACE_REFRESH
,
717 "makech: nsp is at curscr:(%d,%d)\n", wy
, wx
);
719 __CTRACE(__CTRACE_REFRESH
,
720 "makech: nsp is at __virtscr:(%d,%d)\n", wy
, wx
);
722 if (__tc_ce
&& !_cursesi_screen
->curwin
) {
723 cp
= &win
->alines
[wy
]->line
[win
->maxx
- 1];
724 lspc
= cp
->attr
& __COLOR
;
726 while (cp
->ch
== ' ' && cp
->attr
== lspc
) /* XXX */
727 if (cp
-- <= win
->alines
[wy
]->line
)
730 while (cp
->ch
== ( wchar_t )btowc(( int )' ' )
731 && ( cp
->attr
& WA_ATTRIBUTES
) == lspc
)
732 if (cp
-- <= win
->alines
[wy
]->line
)
734 #endif /* HAVE_WCHAR */
735 if (win
->alines
[wy
]->line
> cp
)
738 nlsp
= cp
- win
->alines
[wy
]->line
;
740 if (!_cursesi_screen
->curwin
)
747 __CTRACE(__CTRACE_REFRESH
, "makech: wx=%d,lch=%d\n", wx
, lch
);
750 if (memcmp(nsp
, csp
, sizeof(__LDATA
)) == 0) {
753 memcmp(nsp
, csp
, sizeof(__LDATA
)) == 0) {
755 if (!_cursesi_screen
->curwin
)
765 __CTRACE(__CTRACE_REFRESH
, "makech: nsp=(%x,%x,%x,%x,%p)\n",
766 nsp
->ch
, nsp
->attr
, win
->bch
, win
->battr
, nsp
->nsp
);
767 __CTRACE(__CTRACE_REFRESH
, "makech: csp=(%x,%x,%x,%x,%p)\n",
768 csp
->ch
, csp
->attr
, win
->bch
, win
->battr
, csp
->nsp
);
770 if (((nsp
->attr
& __WCWIDTH
) != __WCWIDTH
) &&
773 while (wx
<= lch
&& cellcmp( csp
, nsp
)) {
775 if (!_cursesi_screen
->curwin
)
783 #endif /* HAVE_WCHAR */
784 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
, wy
, wx
);
787 __CTRACE(__CTRACE_REFRESH
, "makech: 1: wx = %d, ly= %d, "
788 "lx = %d, newy = %d, newx = %d\n",
789 wx
, _cursesi_screen
->ly
, _cursesi_screen
->lx
, wy
, wx
);
791 _cursesi_screen
->ly
= wy
;
792 _cursesi_screen
->lx
= wx
;
794 while (wx
<= lch
&& memcmp(nsp
, csp
, sizeof(__LDATA
)) != 0) {
796 wx
>= nlsp
&& nsp
->ch
== ' ' && nsp
->attr
== lspc
) {
798 while (!cellcmp(nsp
, csp
) && wx
<= lch
) {
799 if (ce
!= NULL
&& wx
>= nlsp
800 && nsp
->ch
== (wchar_t)btowc((int)' ') /* XXX */
801 && (nsp
->attr
& WA_ATTRIBUTES
) == lspc
) {
804 /* Check for clear to end-of-line. */
805 cep
= &curscr
->alines
[wy
]->line
[win
->maxx
- 1];
807 while (cep
->ch
== ' ' && cep
->attr
== lspc
) /* XXX */
809 while (cep
->ch
== (wchar_t)btowc((int)' ')
810 && (cep
->attr
& WA_ATTRIBUTES
) == lspc
)
811 #endif /* HAVE_WCHAR */
814 clsp
= cep
- curscr
->alines
[wy
]->line
-
815 win
->begx
* __LDATASIZE
;
817 __CTRACE(__CTRACE_REFRESH
,
818 "makech: clsp = %zu, nlsp = %zu\n",
821 if (((clsp
- nlsp
>= strlen(__tc_ce
) &&
822 clsp
< win
->maxx
* __LDATASIZE
) ||
823 wy
== win
->maxy
- 1) &&
824 (!(lspc
& __COLOR
) ||
825 ((lspc
& __COLOR
) && __tc_ut
))) {
829 (curscr
->wattr
& __COLOR
)))
830 __set_color(curscr
, lspc
&
832 tputs(__tc_ce
, 0, __cputchar
);
833 _cursesi_screen
->lx
= wx
+ win
->begx
;
834 while (wx
++ <= clsp
) {
837 csp
->ch
= ' '; /* XXX */
839 csp
->ch
= (wchar_t)btowc((int)' ');
841 #endif /* HAVE_WCHAR */
850 __CTRACE(__CTRACE_REFRESH
,
851 "makech: have attr %08x, need attr %08x\n",
852 curscr
->wattr
& WA_ATTRIBUTES
,
853 nsp
->attr
& WA_ATTRIBUTES
);
856 off
= (~nsp
->attr
& curscr
->wattr
)
865 * Unset attributes as appropriate. Unset first
866 * so that the relevant attributes can be reset
867 * (because 'me' unsets 'mb', 'md', 'mh', 'mk',
868 * 'mp' and 'mr'). Check to see if we also turn off
869 * standout, attributes and colour.
871 if (off
& __TERMATTR
&& __tc_me
!= NULL
) {
872 tputs(__tc_me
, 0, __cputchar
);
873 curscr
->wattr
&= __mask_me
;
878 * Exit underscore mode if appropriate.
879 * Check to see if we also turn off standout,
880 * attributes and colour.
882 if (off
& __UNDERSCORE
&& __tc_ue
!= NULL
) {
883 tputs(__tc_ue
, 0, __cputchar
);
884 curscr
->wattr
&= __mask_ue
;
889 * Exit standout mode as appropriate.
890 * Check to see if we also turn off underscore,
891 * attributes and colour.
893 * Should use uc if so/se not available.
895 if (off
& __STANDOUT
&& __tc_se
!= NULL
) {
896 tputs(__tc_se
, 0, __cputchar
);
897 curscr
->wattr
&= __mask_se
;
901 if (off
& __ALTCHARSET
&& __tc_ae
!= NULL
) {
902 tputs(__tc_ae
, 0, __cputchar
);
903 curscr
->wattr
&= ~__ALTCHARSET
;
906 /* Set/change colour as appropriate. */
908 __set_color(curscr
, nsp
->attr
& __COLOR
);
910 on
= (nsp
->attr
& ~curscr
->wattr
)
919 * Enter standout mode if appropriate.
921 if (on
& __STANDOUT
&& __tc_so
!= NULL
&& __tc_se
923 tputs(__tc_so
, 0, __cputchar
);
924 curscr
->wattr
|= __STANDOUT
;
928 * Enter underscore mode if appropriate.
930 * Should use uc if us/ue not available.
932 if (on
& __UNDERSCORE
&& __tc_us
!= NULL
&&
934 tputs(__tc_us
, 0, __cputchar
);
935 curscr
->wattr
|= __UNDERSCORE
;
939 * Set other attributes as appropriate.
941 if (__tc_me
!= NULL
) {
942 if (on
& __BLINK
&& __tc_mb
!= NULL
) {
943 tputs(__tc_mb
, 0, __cputchar
);
944 curscr
->wattr
|= __BLINK
;
946 if (on
& __BOLD
&& __tc_md
!= NULL
) {
947 tputs(__tc_md
, 0, __cputchar
);
948 curscr
->wattr
|= __BOLD
;
950 if (on
& __DIM
&& __tc_mh
!= NULL
) {
951 tputs(__tc_mh
, 0, __cputchar
);
952 curscr
->wattr
|= __DIM
;
954 if (on
& __BLANK
&& __tc_mk
!= NULL
) {
955 tputs(__tc_mk
, 0, __cputchar
);
956 curscr
->wattr
|= __BLANK
;
958 if (on
& __PROTECT
&& __tc_mp
!= NULL
) {
959 tputs(__tc_mp
, 0, __cputchar
);
960 curscr
->wattr
|= __PROTECT
;
962 if (on
& __REVERSE
&& __tc_mr
!= NULL
) {
963 tputs(__tc_mr
, 0, __cputchar
);
964 curscr
->wattr
|= __REVERSE
;
967 if (on
& WA_TOP
&& __tc_Xt
!= NULL
) {
968 tputs(__tc_Xt
, 0, __cputchar
);
969 curscr
->wattr
|= WA_TOP
;
971 if (on
& WA_LOW
&& __tc_Xo
!= NULL
) {
972 tputs(__tc_Xo
, 0, __cputchar
);
973 curscr
->wattr
|= WA_LOW
;
975 if (on
& WA_LEFT
&& __tc_Xl
!= NULL
) {
976 tputs(__tc_Xl
, 0, __cputchar
);
977 curscr
->wattr
|= WA_LEFT
;
979 if (on
& WA_RIGHT
&& __tc_Xl
!= NULL
) {
980 tputs(__tc_Xl
, 0, __cputchar
);
981 curscr
->wattr
|= WA_RIGHT
;
983 if (on
& WA_HORIZONTAL
&& __tc_Xh
!= NULL
) {
984 tputs(__tc_Xh
, 0, __cputchar
);
985 curscr
->wattr
|= WA_HORIZONTAL
;
987 if (on
& WA_VERTICAL
&& __tc_Xv
!= NULL
) {
988 tputs(__tc_Xv
, 0, __cputchar
);
989 curscr
->wattr
|= WA_VERTICAL
;
991 #endif /* HAVE_WCHAR */
994 /* Enter/exit altcharset mode as appropriate. */
995 if (on
& __ALTCHARSET
&& __tc_as
!= NULL
&&
997 tputs(__tc_as
, 0, __cputchar
);
998 curscr
->wattr
|= __ALTCHARSET
;
1002 if (wx
>= win
->maxx
&&
1003 wy
== win
->maxy
- 1 && !_cursesi_screen
->curwin
) {
1004 if (win
->flags
& __SCROLLOK
) {
1005 if (win
->flags
& __ENDLINE
)
1007 if (!(win
->flags
& __SCROLLWIN
)) {
1008 if (!_cursesi_screen
->curwin
) {
1009 csp
->attr
= nsp
->attr
;
1012 if (_cursesi_copy_nsp(nsp
->nsp
, csp
) == ERR
)
1014 #endif /* HAVE_WCHAR */
1017 __cputchar((int) nsp
->ch
);
1019 if ( WCOL( *nsp
) > 0 ) {
1020 __cputwchar((int)nsp
->ch
);
1022 __CTRACE(__CTRACE_REFRESH
,
1023 "makech: (%d,%d)putwchar(0x%x)\n",
1028 * Output non-spacing
1029 * characters for the
1032 __cursesi_putnsp(nsp
->nsp
,
1036 #endif /* HAVE_WCHAR */
1038 if (wx
< curscr
->maxx
) {
1039 domvcur(_cursesi_screen
->ly
, wx
,
1040 (int) (win
->maxy
- 1),
1041 (int) (win
->maxx
- 1));
1043 _cursesi_screen
->ly
= win
->maxy
- 1;
1044 _cursesi_screen
->lx
= win
->maxx
- 1;
1048 if (wx
< win
->maxx
|| wy
< win
->maxy
- 1 ||
1049 !(win
->flags
& __SCROLLWIN
)) {
1050 if (!_cursesi_screen
->curwin
) {
1051 csp
->attr
= nsp
->attr
;
1054 if (_cursesi_copy_nsp(nsp
->nsp
,
1057 #endif /* HAVE_WCHAR */
1061 __cputchar((int) nsp
->ch
);
1063 __CTRACE(__CTRACE_REFRESH
,
1064 "makech: putchar(%c)\n", nsp
->ch
& 0177);
1067 if (WCOL(*nsp
) > 0) {
1068 __cputwchar((int) nsp
->ch
);
1070 __CTRACE(__CTRACE_REFRESH
,
1071 "makech:(%d,%d) putwchar(%x)\n",
1072 wy
, wx
- 1, nsp
->ch
);
1073 __cursesi_putnsp(nsp
->nsp
, wy
, wx
);
1076 #endif /* HAVE_WCHAR */
1078 if (__tc_uc
&& ((nsp
->attr
& __STANDOUT
) ||
1079 (nsp
->attr
& __UNDERSCORE
))) {
1081 tputs(__tc_uc
, 0, __cputchar
);
1085 __CTRACE(__CTRACE_REFRESH
,
1086 "makech: 2: wx = %d, lx = %d\n",
1087 wx
, _cursesi_screen
->lx
);
1090 if (_cursesi_screen
->lx
== wx
) /* If no change. */
1092 _cursesi_screen
->lx
= wx
;
1093 if (_cursesi_screen
->lx
>= COLS
&& __tc_am
)
1094 _cursesi_screen
->lx
= COLS
- 1;
1096 if (wx
>= win
->maxx
) {
1097 domvcur(_cursesi_screen
->ly
,
1098 _cursesi_screen
->lx
,
1099 _cursesi_screen
->ly
,
1100 (int) (win
->maxx
- 1));
1101 _cursesi_screen
->lx
= win
->maxx
- 1;
1104 __CTRACE(__CTRACE_REFRESH
, "makech: 3: wx = %d, lx = %d\n",
1105 wx
, _cursesi_screen
->lx
);
1114 __CTRACE(__CTRACE_REFRESH
,
1115 "makech-after: curscr(%p)-__virtscr(%p)\n",
1116 curscr
, __virtscr
);
1117 for (x
= 0; x
< curscr
->maxx
; x
++) {
1118 lp
= &curscr
->alines
[wy
]->line
[x
];
1119 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
1120 __CTRACE(__CTRACE_REFRESH
,
1121 "[%d,%d](%x,%x,%x,%x,%p)-"
1122 "(%x,%x,%x,%x,%p)\n",
1123 wy
, x
, lp
->ch
, lp
->attr
,
1124 win
->bch
, win
->battr
, lp
->nsp
,
1126 win
->bch
, win
->battr
, vlp
->nsp
);
1129 #endif /* HAVE_WCHAR */
1137 * Do a mvcur, leaving attributes if necessary.
1140 domvcur(oy
, ox
, ny
, nx
)
1144 __CTRACE(__CTRACE_REFRESH
, "domvcur: (%x,%d)=>(%d,%d)\n",
1148 if ( oy
== ny
&& ox
== nx
)
1150 __mvcur(oy
, ox
, ny
, nx
, 1);
1154 * Quickch() attempts to detect a pattern in the change of the window
1155 * in order to optimize the change, e.g., scroll n lines as opposed to
1156 * repainting the screen line by line.
1159 static __LDATA buf
[128];
1160 static u_int last_hash
;
1161 static size_t last_hash_len
;
1162 #define BLANKSIZE (sizeof(buf) / sizeof(buf[0]))
1167 #define THRESH (int) __virtscr->maxy / 4
1169 __LINE
*clp
, *tmp1
, *tmp2
;
1170 int bsize
, curs
, curw
, starts
, startw
, i
, j
;
1171 int n
, target
, cur_period
, bot
, top
, sc_region
;
1176 curs
= curw
= starts
= startw
= 0; /* XXX gcc -Wuninitialized */
1179 * Find how many lines from the top of the screen are unchanged.
1181 for (top
= 0; top
< __virtscr
->maxy
; top
++)
1183 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1184 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1185 memcmp(__virtscr
->alines
[top
]->line
,
1186 curscr
->alines
[top
]->line
,
1187 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1191 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1192 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1193 !linecmp(__virtscr
->alines
[top
]->line
,
1194 curscr
->alines
[top
]->line
,
1195 (size_t) __virtscr
->maxx
)))
1197 #endif /* HAVE_WCHAR */
1199 __virtscr
->alines
[top
]->flags
&= ~__ISDIRTY
;
1201 * Find how many lines from bottom of screen are unchanged.
1203 for (bot
= __virtscr
->maxy
- 1; bot
>= 0; bot
--)
1205 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1206 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1207 memcmp(__virtscr
->alines
[bot
]->line
,
1208 curscr
->alines
[bot
]->line
,
1209 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1213 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1214 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1215 !linecmp(__virtscr
->alines
[bot
]->line
,
1216 curscr
->alines
[bot
]->line
,
1217 (size_t) __virtscr
->maxx
)))
1219 #endif /* HAVE_WCHAR */
1221 __virtscr
->alines
[bot
]->flags
&= ~__ISDIRTY
;
1224 * Work round an xterm bug where inserting lines causes all the
1225 * inserted lines to be covered with the background colour we
1226 * set on the first line (even if we unset it for subsequent
1229 bcolor
= __virtscr
->alines
[min(top
,
1230 __virtscr
->maxy
- 1)]->line
[0].attr
& __COLOR
;
1231 for (i
= top
+ 1, j
= 0; i
< bot
; i
++) {
1232 if ((__virtscr
->alines
[i
]->line
[0].attr
& __COLOR
) != bcolor
) {
1233 bcolor
= __virtscr
->alines
[i
]->line
[__virtscr
->maxx
].
1243 * If we have a bottom unchanged region return. Scrolling the
1244 * bottom region up and then back down causes a screen jitter.
1245 * This will increase the number of characters sent to the screen
1246 * but it looks better.
1248 if (bot
< __virtscr
->maxy
- 1)
1250 #endif /* NO_JERKINESS */
1253 * Search for the largest block of text not changed.
1254 * Invariants of the loop:
1255 * - Startw is the index of the beginning of the examined block in
1257 * - Starts is the index of the beginning of the examined block in
1259 * - Curw is the index of one past the end of the exmined block in
1261 * - Curs is the index of one past the end of the exmined block in
1263 * - bsize is the current size of the examined block.
1266 for (bsize
= bot
- top
; bsize
>= THRESH
; bsize
--) {
1267 for (startw
= top
; startw
<= bot
- bsize
; startw
++)
1268 for (starts
= top
; starts
<= bot
- bsize
;
1270 for (curw
= startw
, curs
= starts
;
1271 curs
< starts
+ bsize
; curw
++, curs
++)
1272 if (__virtscr
->alines
[curw
]->hash
!=
1273 curscr
->alines
[curs
]->hash
)
1275 if (curs
!= starts
+ bsize
)
1277 for (curw
= startw
, curs
= starts
;
1278 curs
< starts
+ bsize
; curw
++, curs
++)
1280 if (memcmp(__virtscr
->alines
[curw
]->line
,
1281 curscr
->alines
[curs
]->line
,
1282 (size_t) __virtscr
->maxx
*
1286 if (!linecmp(__virtscr
->alines
[curw
]->line
,
1287 curscr
->alines
[curs
]->line
,
1288 (size_t) __virtscr
->maxx
))
1290 #endif /* HAVE_WCHAR */
1291 if (curs
== starts
+ bsize
)
1297 /* Did not find anything */
1302 __CTRACE(__CTRACE_REFRESH
, "quickch:bsize=%d, starts=%d, startw=%d, "
1303 "curw=%d, curs=%d, top=%d, bot=%d\n",
1304 bsize
, starts
, startw
, curw
, curs
, top
, bot
);
1308 * Make sure that there is no overlap between the bottom and top
1309 * regions and the middle scrolled block.
1316 n
= startw
- starts
;
1319 __CTRACE(__CTRACE_REFRESH
, "#####################################\n");
1320 for (i
= 0; i
< curscr
->maxy
; i
++) {
1321 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1322 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n", curscr
->alines
[i
]->hash
);
1323 for (j
= 0; j
< curscr
->maxx
; j
++)
1324 __CTRACE(__CTRACE_REFRESH
, "%c",
1325 curscr
->alines
[i
]->line
[j
].ch
);
1326 __CTRACE(__CTRACE_REFRESH
, "\n");
1327 __CTRACE(__CTRACE_REFRESH
, " attr:");
1328 for (j
= 0; j
< curscr
->maxx
; j
++)
1329 __CTRACE(__CTRACE_REFRESH
, " %x",
1330 curscr
->alines
[i
]->line
[j
].attr
);
1331 __CTRACE(__CTRACE_REFRESH
, "\n");
1332 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1333 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
1334 __virtscr
->alines
[i
]->hash
);
1335 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
1336 __virtscr
->alines
[i
]->flags
);
1337 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1338 __CTRACE(__CTRACE_REFRESH
, "%c",
1339 __virtscr
->alines
[i
]->line
[j
].ch
);
1340 __CTRACE(__CTRACE_REFRESH
, "\n");
1341 __CTRACE(__CTRACE_REFRESH
, " attr:");
1342 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1343 __CTRACE(__CTRACE_REFRESH
, " %x",
1344 __virtscr
->alines
[i
]->line
[j
].attr
);
1345 __CTRACE(__CTRACE_REFRESH
, "\n");
1350 if (buf
[0].ch
!= ' ') {
1351 for (i
= 0; i
< BLANKSIZE
; i
++) {
1357 if (buf
[0].ch
!= ( wchar_t )btowc(( int ) curscr
->bch
)) {
1358 for (i
= 0; i
< BLANKSIZE
; i
++) {
1359 buf
[i
].ch
= ( wchar_t )btowc(( int ) curscr
->bch
);
1360 if (_cursesi_copy_nsp(curscr
->bnsp
, &buf
[i
]) == ERR
)
1363 SET_WCOL( buf
[ i
], 1 );
1366 #endif /* HAVE_WCHAR */
1368 if (__virtscr
->maxx
!= last_hash_len
) {
1370 for (i
= __virtscr
->maxx
; i
> BLANKSIZE
; i
-= BLANKSIZE
) {
1371 blank_hash
= __hash_more(buf
, sizeof(buf
), blank_hash
);
1373 blank_hash
= __hash_more((char *)(void *)buf
,
1374 i
* sizeof(buf
[0]), blank_hash
);
1375 /* cache result in static data - screen width doesn't change often */
1376 last_hash_len
= __virtscr
->maxx
;
1377 last_hash
= blank_hash
;
1379 blank_hash
= last_hash
;
1382 * Perform the rotation to maintain the consistency of curscr.
1383 * This is hairy since we are doing an *in place* rotation.
1384 * Invariants of the loop:
1385 * - I is the index of the current line.
1386 * - Target is the index of the target of line i.
1387 * - Tmp1 points to current line (i).
1388 * - Tmp2 and points to target line (target);
1389 * - Cur_period is the index of the end of the current period.
1392 * There are 2 major issues here that make this rotation non-trivial:
1393 * 1. Scrolling in a scrolling region bounded by the top
1394 * and bottom regions determined (whose size is sc_region).
1395 * 2. As a result of the use of the mod function, there may be a
1396 * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
1397 * 0 to 2, which then causes all odd lines not to be rotated.
1398 * To remedy this, an index of the end ( = beginning) of the
1399 * current 'period' is kept, cur_period, and when it is reached,
1400 * the next period is started from cur_period + 1 which is
1401 * guaranteed not to have been reached since that would mean that
1402 * all records would have been reached. (think about it...).
1404 * Lines in the rotation can have 3 attributes which are marked on the
1405 * line so that curscr is consistent with the visual screen.
1406 * 1. Not dirty -- lines inside the scrolled block, top region or
1408 * 2. Blank lines -- lines in the differential of the scrolling
1409 * region adjacent to top and bot regions
1410 * depending on scrolling direction.
1411 * 3. Dirty line -- all other lines are marked dirty.
1413 sc_region
= bot
- top
+ 1;
1415 tmp1
= curscr
->alines
[top
];
1417 for (j
= top
; j
<= bot
; j
++) {
1418 target
= (i
- top
+ n
+ sc_region
) % sc_region
+ top
;
1419 tmp2
= curscr
->alines
[target
];
1420 curscr
->alines
[target
] = tmp1
;
1421 /* Mark block as clean and blank out scrolled lines. */
1422 clp
= curscr
->alines
[target
];
1424 __CTRACE(__CTRACE_REFRESH
,
1425 "quickch: n=%d startw=%d curw=%d i = %d target=%d ",
1426 n
, startw
, curw
, i
, target
);
1428 if ((target
>= startw
&& target
< curw
) || target
< top
1431 __CTRACE(__CTRACE_REFRESH
, " notdirty\n");
1433 __virtscr
->alines
[target
]->flags
&= ~__ISDIRTY
;
1435 if ((n
> 0 && target
>= top
&& target
< top
+ n
) ||
1436 (n
< 0 && target
<= bot
&& target
> bot
+ n
)) {
1438 if (clp
->hash
!= blank_hash
||
1439 memcmp(clp
->line
, clp
->line
+ 1,
1440 (__virtscr
->maxx
- 1)
1442 memcmp(clp
->line
, buf
, __LDATASIZE
)) {
1444 if (clp
->hash
!= blank_hash
1445 || linecmp(clp
->line
, clp
->line
+ 1,
1446 (unsigned int) (__virtscr
->maxx
- 1))
1447 || cellcmp(clp
->line
, buf
)) {
1448 #endif /* HAVE_WCHAR */
1449 for (i
= __virtscr
->maxx
;
1452 (void) memcpy(clp
->line
+ i
-
1453 BLANKSIZE
, buf
, sizeof(buf
));
1455 (void) memcpy(clp
->line
, buf
, i
*
1458 __CTRACE(__CTRACE_REFRESH
,
1459 " blanked out: dirty\n");
1461 clp
->hash
= blank_hash
;
1462 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1465 __CTRACE(__CTRACE_REFRESH
,
1466 " -- blank line already: dirty\n");
1468 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1472 __CTRACE(__CTRACE_REFRESH
, " -- dirty\n");
1474 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1476 if (target
== cur_period
) {
1478 tmp1
= curscr
->alines
[i
];
1486 __CTRACE(__CTRACE_REFRESH
, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
1487 for (i
= 0; i
< curscr
->maxy
; i
++) {
1488 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1489 for (j
= 0; j
< curscr
->maxx
; j
++)
1490 __CTRACE(__CTRACE_REFRESH
, "%c",
1491 curscr
->alines
[i
]->line
[j
].ch
);
1492 __CTRACE(__CTRACE_REFRESH
, "\n");
1493 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1494 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1495 __CTRACE(__CTRACE_REFRESH
, "%c",
1496 __virtscr
->alines
[i
]->line
[j
].ch
);
1497 __CTRACE(__CTRACE_REFRESH
, "\n");
1501 scrolln(starts
, startw
, curs
, bot
, top
);
1506 * Scroll n lines, where n is starts - startw.
1508 static void /* ARGSUSED */
1509 scrolln(starts
, startw
, curs
, bot
, top
)
1510 int starts
, startw
, curs
, bot
, top
;
1516 n
= starts
- startw
;
1520 * The initial tests that set __noqch don't let us reach here unless
1521 * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
1522 * scrolling can only shift the entire scrolling region, not just a
1523 * part of it, which means that the quickch() routine is going to be
1524 * sadly disappointed in us if we don't have cs as well.
1526 * If cs, ho and SF/sf are set, can use the scrolling region. Because
1527 * the cursor position after cs is undefined, we need ho which gives us
1528 * the ability to move to somewhere without knowledge of the current
1529 * location of the cursor. Still call __mvcur() anyway, to update its
1530 * idea of where the cursor is.
1532 * When the scrolling region has been set, the cursor has to be at the
1533 * last line of the region to make the scroll happen.
1535 * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr
1536 * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not
1537 * SF/SR. So, if we're scrolling almost all of the screen, try and use
1538 * AL/DL, otherwise use the scrolling region. The "almost all" is a
1539 * shameless hack for vi.
1542 if (__tc_cs
!= NULL
&& __tc_ho
!= NULL
&& (__tc_SF
!= NULL
||
1543 ((__tc_AL
== NULL
|| __tc_DL
== NULL
||
1544 top
> 3 || bot
+ 3 < __virtscr
->maxy
) &&
1545 __tc_sf
!= NULL
))) {
1546 tputs(__tscroll(__tc_cs
, top
, bot
+ 1), 0, __cputchar
);
1547 __mvcur(oy
, ox
, 0, 0, 1);
1548 tputs(__tc_ho
, 0, __cputchar
);
1549 __mvcur(0, 0, bot
, 0, 1);
1550 if (__tc_SF
!= NULL
)
1551 tputs(__tscroll(__tc_SF
, n
, 0), 0, __cputchar
);
1553 for (i
= 0; i
< n
; i
++)
1554 tputs(__tc_sf
, 0, __cputchar
);
1555 tputs(__tscroll(__tc_cs
, 0, (int) __virtscr
->maxy
), 0,
1557 __mvcur(bot
, 0, 0, 0, 1);
1558 tputs(__tc_ho
, 0, __cputchar
);
1559 __mvcur(0, 0, oy
, ox
, 1);
1563 /* Scroll up the block. */
1564 if (__tc_SF
!= NULL
&& top
== 0) {
1565 __mvcur(oy
, ox
, bot
, 0, 1);
1566 tputs(__tscroll(__tc_SF
, n
, 0), 0, __cputchar
);
1568 if (__tc_DL
!= NULL
) {
1569 __mvcur(oy
, ox
, top
, 0, 1);
1570 tputs(__tscroll(__tc_DL
, n
, 0), 0, __cputchar
);
1572 if (__tc_dl
!= NULL
) {
1573 __mvcur(oy
, ox
, top
, 0, 1);
1574 for (i
= 0; i
< n
; i
++)
1575 tputs(__tc_dl
, 0, __cputchar
);
1577 if (__tc_sf
!= NULL
&& top
== 0) {
1578 __mvcur(oy
, ox
, bot
, 0, 1);
1579 for (i
= 0; i
< n
; i
++)
1585 /* Push down the bottom region. */
1586 __mvcur(top
, 0, bot
- n
+ 1, 0, 1);
1587 if (__tc_AL
!= NULL
)
1588 tputs(__tscroll(__tc_AL
, n
, 0), 0, __cputchar
);
1590 if (__tc_al
!= NULL
)
1591 for (i
= 0; i
< n
; i
++)
1592 tputs(__tc_al
, 0, __cputchar
);
1595 __mvcur(bot
- n
+ 1, 0, oy
, ox
, 1);
1601 * If cs, ho and SR/sr are set, can use the scrolling region.
1602 * See the above comments for details.
1604 if (__tc_cs
!= NULL
&& __tc_ho
!= NULL
&& (__tc_SR
!= NULL
||
1605 ((__tc_AL
== NULL
|| __tc_DL
== NULL
|| top
> 3 ||
1606 bot
+ 3 < __virtscr
->maxy
) && __tc_sr
!= NULL
))) {
1607 tputs(__tscroll(__tc_cs
, top
, bot
+ 1), 0, __cputchar
);
1608 __mvcur(oy
, ox
, 0, 0, 1);
1609 tputs(__tc_ho
, 0, __cputchar
);
1610 __mvcur(0, 0, top
, 0, 1);
1612 if (__tc_SR
!= NULL
)
1613 tputs(__tscroll(__tc_SR
, -n
, 0), 0, __cputchar
);
1615 for (i
= n
; i
< 0; i
++)
1616 tputs(__tc_sr
, 0, __cputchar
);
1617 tputs(__tscroll(__tc_cs
, 0, (int) __virtscr
->maxy
), 0,
1619 __mvcur(top
, 0, 0, 0, 1);
1620 tputs(__tc_ho
, 0, __cputchar
);
1621 __mvcur(0, 0, oy
, ox
, 1);
1625 /* Preserve the bottom lines. */
1626 __mvcur(oy
, ox
, bot
+ n
+ 1, 0, 1);
1627 if (__tc_SR
!= NULL
&& bot
== __virtscr
->maxy
)
1628 tputs(__tscroll(__tc_SR
, -n
, 0), 0, __cputchar
);
1630 if (__tc_DL
!= NULL
)
1631 tputs(__tscroll(__tc_DL
, -n
, 0), 0, __cputchar
);
1633 if (__tc_dl
!= NULL
)
1634 for (i
= n
; i
< 0; i
++)
1635 tputs(__tc_dl
, 0, __cputchar
);
1637 if (__tc_sr
!= NULL
&&
1638 bot
== __virtscr
->maxy
)
1639 for (i
= n
; i
< 0; i
++)
1645 /* Scroll the block down. */
1646 __mvcur(bot
+ n
+ 1, 0, top
, 0, 1);
1647 if (__tc_AL
!= NULL
)
1648 tputs(__tscroll(__tc_AL
, -n
, 0), 0, __cputchar
);
1650 if (__tc_al
!= NULL
)
1651 for (i
= n
; i
< 0; i
++)
1652 tputs(__tc_al
, 0, __cputchar
);
1655 __mvcur(top
, 0, oy
, ox
, 1);
1661 * Unset attributes on curscr. Leave standout, attribute and colour
1662 * modes if necessary (!ms). Always leave altcharset (xterm at least
1663 * ignores a cursor move if we don't).
1666 __unsetattr(int checkms
)
1679 __CTRACE(__CTRACE_REFRESH
,
1680 "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n",
1681 checkms
, __tc_ms
? "TRUE" : "FALSE", curscr
->wattr
);
1685 * Don't leave the screen in standout mode (check against ms). Check
1686 * to see if we also turn off underscore, attributes and colour.
1688 if (curscr
->wattr
& __STANDOUT
&& isms
) {
1689 tputs(__tc_se
, 0, __cputchar
);
1690 curscr
->wattr
&= __mask_se
;
1693 * Don't leave the screen in underscore mode (check against ms).
1694 * Check to see if we also turn off attributes. Assume that we
1695 * also turn off colour.
1697 if (curscr
->wattr
& __UNDERSCORE
&& isms
) {
1698 tputs(__tc_ue
, 0, __cputchar
);
1699 curscr
->wattr
&= __mask_ue
;
1702 * Don't leave the screen with attributes set (check against ms).
1703 * Assume that also turn off colour.
1705 if (curscr
->wattr
& __TERMATTR
&& isms
) {
1706 tputs(__tc_me
, 0, __cputchar
);
1707 curscr
->wattr
&= __mask_me
;
1709 /* Don't leave the screen with altcharset set (don't check ms). */
1710 if (curscr
->wattr
& __ALTCHARSET
) {
1711 tputs(__tc_ae
, 0, __cputchar
);
1712 curscr
->wattr
&= ~__ALTCHARSET
;
1714 /* Don't leave the screen with colour set (check against ms). */
1715 if (__using_color
&& isms
)
1716 __unset_color(curscr
);
1720 /* compare two cells on screen, must have the same forground/background,
1721 * and the same sequence of non-spacing characters */
1723 cellcmp( __LDATA
*x
, __LDATA
*y
)
1725 nschar_t
*xnp
= x
->nsp
, *ynp
= y
->nsp
;
1726 int ret
= ( x
->ch
== y
->ch
) & ( x
->attr
== y
->attr
);
1732 if (( xnp
&& !ynp
) || ( !xnp
&& ynp
))
1735 while ( xnp
&& ynp
) {
1736 if ( xnp
->ch
!= ynp
->ch
)
1741 return ( !xnp
&& !ynp
);
1744 /* compare two line segments */
1746 linecmp( __LDATA
*xl
, __LDATA
*yl
, size_t len
)
1749 __LDATA
*xp
= xl
, *yp
= yl
;
1751 for ( i
= 0; i
< len
; i
++, xp
++, yp
++ ) {
1752 if ( !cellcmp( xp
, yp
))
1759 * Output the non-spacing characters associated with the given character
1760 * cell to the screen.
1764 __cursesi_putnsp(nschar_t
*nsp
, const int wy
, const int wx
)
1768 /* this shuts up gcc warnings about wx and wy not being used */
1774 __cputwchar((int) p
->ch
);
1776 __CTRACE(__CTRACE_REFRESH
,
1777 "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n",
1784 #endif /* HAVE_WCHAR */