1 /* $NetBSD: refresh.c,v 1.73 2010/02/08 20:45:22 roy 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.73 2010/02/08 20:45:22 roy 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(clear_screen
, 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
;
462 if (!cursor_address
) {
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 (clr_eol
&& !_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(clr_eol
) &&
822 clsp
< win
->maxx
* __LDATASIZE
) ||
823 wy
== win
->maxy
- 1) &&
824 (!(lspc
& __COLOR
) ||
825 ((lspc
& __COLOR
) && back_color_erase
))) {
829 (curscr
->wattr
& __COLOR
)))
830 __set_color(curscr
, lspc
&
832 tputs(clr_eol
, 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
&& exit_attribute_mode
!= NULL
) {
872 tputs(exit_attribute_mode
, 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
&& exit_underline_mode
!= NULL
) {
883 tputs(exit_underline_mode
, 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
&& exit_standout_mode
!= NULL
) {
896 tputs(exit_standout_mode
, 0, __cputchar
);
897 curscr
->wattr
&= __mask_se
;
901 if (off
& __ALTCHARSET
&& exit_alt_charset_mode
!= NULL
) {
902 tputs(exit_alt_charset_mode
, 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
&&
922 enter_standout_mode
!= NULL
&&
923 exit_standout_mode
!= NULL
)
925 tputs(enter_standout_mode
, 0, __cputchar
);
926 curscr
->wattr
|= __STANDOUT
;
930 * Enter underscore mode if appropriate.
932 * Should use uc if us/ue not available.
934 if (on
& __UNDERSCORE
&&
935 enter_underline_mode
!= NULL
&&
936 exit_underline_mode
!= NULL
)
938 tputs(enter_underline_mode
, 0, __cputchar
);
939 curscr
->wattr
|= __UNDERSCORE
;
943 * Set other attributes as appropriate.
945 if (exit_attribute_mode
!= NULL
) {
947 enter_blink_mode
!= NULL
)
949 tputs(enter_blink_mode
, 0, __cputchar
);
950 curscr
->wattr
|= __BLINK
;
953 enter_bold_mode
!= NULL
)
955 tputs(enter_bold_mode
, 0, __cputchar
);
956 curscr
->wattr
|= __BOLD
;
959 enter_dim_mode
!= NULL
)
961 tputs(enter_dim_mode
, 0, __cputchar
);
962 curscr
->wattr
|= __DIM
;
965 enter_secure_mode
!= NULL
)
967 tputs(enter_secure_mode
, 0, __cputchar
);
968 curscr
->wattr
|= __BLANK
;
970 if (on
& __PROTECT
&&
971 enter_protected_mode
!= NULL
)
973 tputs(enter_protected_mode
, 0, __cputchar
);
974 curscr
->wattr
|= __PROTECT
;
976 if (on
& __REVERSE
&&
977 enter_reverse_mode
!= NULL
)
979 tputs(enter_reverse_mode
, 0, __cputchar
);
980 curscr
->wattr
|= __REVERSE
;
984 enter_top_hl_mode
!= NULL
)
986 tputs(enter_top_hl_mode
, 0, __cputchar
);
987 curscr
->wattr
|= WA_TOP
;
990 enter_low_hl_mode
!= NULL
)
992 tputs(enter_low_hl_mode
, 0, __cputchar
);
993 curscr
->wattr
|= WA_LOW
;
996 enter_left_hl_mode
!= NULL
)
998 tputs(enter_left_hl_mode
, 0, __cputchar
);
999 curscr
->wattr
|= WA_LEFT
;
1001 if (on
& WA_RIGHT
&&
1002 enter_right_hl_mode
!= NULL
)
1004 tputs(enter_right_hl_mode
, 0, __cputchar
);
1005 curscr
->wattr
|= WA_RIGHT
;
1007 if (on
& WA_HORIZONTAL
&&
1008 enter_horizontal_hl_mode
!= NULL
)
1010 tputs(enter_horizontal_hl_mode
, 0, __cputchar
);
1011 curscr
->wattr
|= WA_HORIZONTAL
;
1013 if (on
& WA_VERTICAL
&&
1014 enter_vertical_hl_mode
!= NULL
)
1016 tputs(enter_vertical_hl_mode
, 0, __cputchar
);
1017 curscr
->wattr
|= WA_VERTICAL
;
1019 #endif /* HAVE_WCHAR */
1022 /* Enter/exit altcharset mode as appropriate. */
1023 if (on
& __ALTCHARSET
&& enter_alt_charset_mode
!= NULL
&&
1024 exit_alt_charset_mode
!= NULL
) {
1025 tputs(enter_alt_charset_mode
, 0, __cputchar
);
1026 curscr
->wattr
|= __ALTCHARSET
;
1030 if (wx
>= win
->maxx
&&
1031 wy
== win
->maxy
- 1 && !_cursesi_screen
->curwin
) {
1032 if (win
->flags
& __SCROLLOK
) {
1033 if (win
->flags
& __ENDLINE
)
1035 if (!(win
->flags
& __SCROLLWIN
)) {
1036 if (!_cursesi_screen
->curwin
) {
1037 csp
->attr
= nsp
->attr
;
1040 if (_cursesi_copy_nsp(nsp
->nsp
, csp
) == ERR
)
1042 #endif /* HAVE_WCHAR */
1045 __cputchar((int) nsp
->ch
);
1047 if ( WCOL( *nsp
) > 0 ) {
1048 __cputwchar((int)nsp
->ch
);
1050 __CTRACE(__CTRACE_REFRESH
,
1051 "makech: (%d,%d)putwchar(0x%x)\n",
1056 * Output non-spacing
1057 * characters for the
1060 __cursesi_putnsp(nsp
->nsp
,
1064 #endif /* HAVE_WCHAR */
1066 if (wx
< curscr
->maxx
) {
1067 domvcur(_cursesi_screen
->ly
, wx
,
1068 (int) (win
->maxy
- 1),
1069 (int) (win
->maxx
- 1));
1071 _cursesi_screen
->ly
= win
->maxy
- 1;
1072 _cursesi_screen
->lx
= win
->maxx
- 1;
1076 if (wx
< win
->maxx
|| wy
< win
->maxy
- 1 ||
1077 !(win
->flags
& __SCROLLWIN
)) {
1078 if (!_cursesi_screen
->curwin
) {
1079 csp
->attr
= nsp
->attr
;
1082 if (_cursesi_copy_nsp(nsp
->nsp
,
1085 #endif /* HAVE_WCHAR */
1089 __cputchar((int) nsp
->ch
);
1091 __CTRACE(__CTRACE_REFRESH
,
1092 "makech: putchar(%c)\n", nsp
->ch
& 0177);
1095 if (WCOL(*nsp
) > 0) {
1096 __cputwchar((int) nsp
->ch
);
1098 __CTRACE(__CTRACE_REFRESH
,
1099 "makech:(%d,%d) putwchar(%x)\n",
1100 wy
, wx
- 1, nsp
->ch
);
1101 __cursesi_putnsp(nsp
->nsp
, wy
, wx
);
1104 #endif /* HAVE_WCHAR */
1106 if (underline_char
&& ((nsp
->attr
& __STANDOUT
) ||
1107 (nsp
->attr
& __UNDERSCORE
))) {
1109 tputs(underline_char
, 0, __cputchar
);
1113 __CTRACE(__CTRACE_REFRESH
,
1114 "makech: 2: wx = %d, lx = %d\n",
1115 wx
, _cursesi_screen
->lx
);
1118 if (_cursesi_screen
->lx
== wx
) /* If no change. */
1120 _cursesi_screen
->lx
= wx
;
1121 if (_cursesi_screen
->lx
>= COLS
&& auto_right_margin
)
1122 _cursesi_screen
->lx
= COLS
- 1;
1124 if (wx
>= win
->maxx
) {
1125 domvcur(_cursesi_screen
->ly
,
1126 _cursesi_screen
->lx
,
1127 _cursesi_screen
->ly
,
1128 (int) (win
->maxx
- 1));
1129 _cursesi_screen
->lx
= win
->maxx
- 1;
1132 __CTRACE(__CTRACE_REFRESH
, "makech: 3: wx = %d, lx = %d\n",
1133 wx
, _cursesi_screen
->lx
);
1142 __CTRACE(__CTRACE_REFRESH
,
1143 "makech-after: curscr(%p)-__virtscr(%p)\n",
1144 curscr
, __virtscr
);
1145 for (x
= 0; x
< curscr
->maxx
; x
++) {
1146 lp
= &curscr
->alines
[wy
]->line
[x
];
1147 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
1148 __CTRACE(__CTRACE_REFRESH
,
1149 "[%d,%d](%x,%x,%x,%x,%p)-"
1150 "(%x,%x,%x,%x,%p)\n",
1151 wy
, x
, lp
->ch
, lp
->attr
,
1152 win
->bch
, win
->battr
, lp
->nsp
,
1154 win
->bch
, win
->battr
, vlp
->nsp
);
1157 #endif /* HAVE_WCHAR */
1165 * Do a mvcur, leaving attributes if necessary.
1168 domvcur(oy
, ox
, ny
, nx
)
1172 __CTRACE(__CTRACE_REFRESH
, "domvcur: (%x,%d)=>(%d,%d)\n",
1176 if ( oy
== ny
&& ox
== nx
)
1178 __mvcur(oy
, ox
, ny
, nx
, 1);
1182 * Quickch() attempts to detect a pattern in the change of the window
1183 * in order to optimize the change, e.g., scroll n lines as opposed to
1184 * repainting the screen line by line.
1187 static __LDATA buf
[128];
1188 static u_int last_hash
;
1189 static size_t last_hash_len
;
1190 #define BLANKSIZE (sizeof(buf) / sizeof(buf[0]))
1195 #define THRESH (int) __virtscr->maxy / 4
1197 __LINE
*clp
, *tmp1
, *tmp2
;
1198 int bsize
, curs
, curw
, starts
, startw
, i
, j
;
1199 int n
, target
, cur_period
, bot
, top
, sc_region
;
1204 curs
= curw
= starts
= startw
= 0; /* XXX gcc -Wuninitialized */
1207 * Find how many lines from the top of the screen are unchanged.
1209 for (top
= 0; top
< __virtscr
->maxy
; top
++)
1211 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1212 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1213 memcmp(__virtscr
->alines
[top
]->line
,
1214 curscr
->alines
[top
]->line
,
1215 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1219 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1220 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1221 !linecmp(__virtscr
->alines
[top
]->line
,
1222 curscr
->alines
[top
]->line
,
1223 (size_t) __virtscr
->maxx
)))
1225 #endif /* HAVE_WCHAR */
1227 __virtscr
->alines
[top
]->flags
&= ~__ISDIRTY
;
1229 * Find how many lines from bottom of screen are unchanged.
1231 for (bot
= __virtscr
->maxy
- 1; bot
>= 0; bot
--)
1233 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1234 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1235 memcmp(__virtscr
->alines
[bot
]->line
,
1236 curscr
->alines
[bot
]->line
,
1237 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1241 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1242 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1243 !linecmp(__virtscr
->alines
[bot
]->line
,
1244 curscr
->alines
[bot
]->line
,
1245 (size_t) __virtscr
->maxx
)))
1247 #endif /* HAVE_WCHAR */
1249 __virtscr
->alines
[bot
]->flags
&= ~__ISDIRTY
;
1252 * Work round an xterm bug where inserting lines causes all the
1253 * inserted lines to be covered with the background colour we
1254 * set on the first line (even if we unset it for subsequent
1257 bcolor
= __virtscr
->alines
[min(top
,
1258 __virtscr
->maxy
- 1)]->line
[0].attr
& __COLOR
;
1259 for (i
= top
+ 1, j
= 0; i
< bot
; i
++) {
1260 if ((__virtscr
->alines
[i
]->line
[0].attr
& __COLOR
) != bcolor
) {
1261 bcolor
= __virtscr
->alines
[i
]->line
[__virtscr
->maxx
].
1271 * If we have a bottom unchanged region return. Scrolling the
1272 * bottom region up and then back down causes a screen jitter.
1273 * This will increase the number of characters sent to the screen
1274 * but it looks better.
1276 if (bot
< __virtscr
->maxy
- 1)
1278 #endif /* NO_JERKINESS */
1281 * Search for the largest block of text not changed.
1282 * Invariants of the loop:
1283 * - Startw is the index of the beginning of the examined block in
1285 * - Starts is the index of the beginning of the examined block in
1287 * - Curw is the index of one past the end of the exmined block in
1289 * - Curs is the index of one past the end of the exmined block in
1291 * - bsize is the current size of the examined block.
1294 for (bsize
= bot
- top
; bsize
>= THRESH
; bsize
--) {
1295 for (startw
= top
; startw
<= bot
- bsize
; startw
++)
1296 for (starts
= top
; starts
<= bot
- bsize
;
1298 for (curw
= startw
, curs
= starts
;
1299 curs
< starts
+ bsize
; curw
++, curs
++)
1300 if (__virtscr
->alines
[curw
]->hash
!=
1301 curscr
->alines
[curs
]->hash
)
1303 if (curs
!= starts
+ bsize
)
1305 for (curw
= startw
, curs
= starts
;
1306 curs
< starts
+ bsize
; curw
++, curs
++)
1308 if (memcmp(__virtscr
->alines
[curw
]->line
,
1309 curscr
->alines
[curs
]->line
,
1310 (size_t) __virtscr
->maxx
*
1314 if (!linecmp(__virtscr
->alines
[curw
]->line
,
1315 curscr
->alines
[curs
]->line
,
1316 (size_t) __virtscr
->maxx
))
1318 #endif /* HAVE_WCHAR */
1319 if (curs
== starts
+ bsize
)
1325 /* Did not find anything */
1330 __CTRACE(__CTRACE_REFRESH
, "quickch:bsize=%d, starts=%d, startw=%d, "
1331 "curw=%d, curs=%d, top=%d, bot=%d\n",
1332 bsize
, starts
, startw
, curw
, curs
, top
, bot
);
1336 * Make sure that there is no overlap between the bottom and top
1337 * regions and the middle scrolled block.
1344 n
= startw
- starts
;
1347 __CTRACE(__CTRACE_REFRESH
, "#####################################\n");
1348 for (i
= 0; i
< curscr
->maxy
; i
++) {
1349 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1350 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n", curscr
->alines
[i
]->hash
);
1351 for (j
= 0; j
< curscr
->maxx
; j
++)
1352 __CTRACE(__CTRACE_REFRESH
, "%c",
1353 curscr
->alines
[i
]->line
[j
].ch
);
1354 __CTRACE(__CTRACE_REFRESH
, "\n");
1355 __CTRACE(__CTRACE_REFRESH
, " attr:");
1356 for (j
= 0; j
< curscr
->maxx
; j
++)
1357 __CTRACE(__CTRACE_REFRESH
, " %x",
1358 curscr
->alines
[i
]->line
[j
].attr
);
1359 __CTRACE(__CTRACE_REFRESH
, "\n");
1360 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1361 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
1362 __virtscr
->alines
[i
]->hash
);
1363 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
1364 __virtscr
->alines
[i
]->flags
);
1365 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1366 __CTRACE(__CTRACE_REFRESH
, "%c",
1367 __virtscr
->alines
[i
]->line
[j
].ch
);
1368 __CTRACE(__CTRACE_REFRESH
, "\n");
1369 __CTRACE(__CTRACE_REFRESH
, " attr:");
1370 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1371 __CTRACE(__CTRACE_REFRESH
, " %x",
1372 __virtscr
->alines
[i
]->line
[j
].attr
);
1373 __CTRACE(__CTRACE_REFRESH
, "\n");
1378 if (buf
[0].ch
!= ' ') {
1379 for (i
= 0; i
< BLANKSIZE
; i
++) {
1385 if (buf
[0].ch
!= ( wchar_t )btowc(( int ) curscr
->bch
)) {
1386 for (i
= 0; i
< BLANKSIZE
; i
++) {
1387 buf
[i
].ch
= ( wchar_t )btowc(( int ) curscr
->bch
);
1388 if (_cursesi_copy_nsp(curscr
->bnsp
, &buf
[i
]) == ERR
)
1391 SET_WCOL( buf
[ i
], 1 );
1394 #endif /* HAVE_WCHAR */
1396 if (__virtscr
->maxx
!= last_hash_len
) {
1398 for (i
= __virtscr
->maxx
; i
> BLANKSIZE
; i
-= BLANKSIZE
) {
1399 blank_hash
= __hash_more(buf
, sizeof(buf
), blank_hash
);
1401 blank_hash
= __hash_more((char *)(void *)buf
,
1402 i
* sizeof(buf
[0]), blank_hash
);
1403 /* cache result in static data - screen width doesn't change often */
1404 last_hash_len
= __virtscr
->maxx
;
1405 last_hash
= blank_hash
;
1407 blank_hash
= last_hash
;
1410 * Perform the rotation to maintain the consistency of curscr.
1411 * This is hairy since we are doing an *in place* rotation.
1412 * Invariants of the loop:
1413 * - I is the index of the current line.
1414 * - Target is the index of the target of line i.
1415 * - Tmp1 points to current line (i).
1416 * - Tmp2 and points to target line (target);
1417 * - Cur_period is the index of the end of the current period.
1420 * There are 2 major issues here that make this rotation non-trivial:
1421 * 1. Scrolling in a scrolling region bounded by the top
1422 * and bottom regions determined (whose size is sc_region).
1423 * 2. As a result of the use of the mod function, there may be a
1424 * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
1425 * 0 to 2, which then causes all odd lines not to be rotated.
1426 * To remedy this, an index of the end ( = beginning) of the
1427 * current 'period' is kept, cur_period, and when it is reached,
1428 * the next period is started from cur_period + 1 which is
1429 * guaranteed not to have been reached since that would mean that
1430 * all records would have been reached. (think about it...).
1432 * Lines in the rotation can have 3 attributes which are marked on the
1433 * line so that curscr is consistent with the visual screen.
1434 * 1. Not dirty -- lines inside the scrolled block, top region or
1436 * 2. Blank lines -- lines in the differential of the scrolling
1437 * region adjacent to top and bot regions
1438 * depending on scrolling direction.
1439 * 3. Dirty line -- all other lines are marked dirty.
1441 sc_region
= bot
- top
+ 1;
1443 tmp1
= curscr
->alines
[top
];
1445 for (j
= top
; j
<= bot
; j
++) {
1446 target
= (i
- top
+ n
+ sc_region
) % sc_region
+ top
;
1447 tmp2
= curscr
->alines
[target
];
1448 curscr
->alines
[target
] = tmp1
;
1449 /* Mark block as clean and blank out scrolled lines. */
1450 clp
= curscr
->alines
[target
];
1452 __CTRACE(__CTRACE_REFRESH
,
1453 "quickch: n=%d startw=%d curw=%d i = %d target=%d ",
1454 n
, startw
, curw
, i
, target
);
1456 if ((target
>= startw
&& target
< curw
) || target
< top
1459 __CTRACE(__CTRACE_REFRESH
, " notdirty\n");
1461 __virtscr
->alines
[target
]->flags
&= ~__ISDIRTY
;
1463 if ((n
> 0 && target
>= top
&& target
< top
+ n
) ||
1464 (n
< 0 && target
<= bot
&& target
> bot
+ n
)) {
1466 if (clp
->hash
!= blank_hash
||
1467 memcmp(clp
->line
, clp
->line
+ 1,
1468 (__virtscr
->maxx
- 1)
1470 memcmp(clp
->line
, buf
, __LDATASIZE
)) {
1472 if (clp
->hash
!= blank_hash
1473 || linecmp(clp
->line
, clp
->line
+ 1,
1474 (unsigned int) (__virtscr
->maxx
- 1))
1475 || cellcmp(clp
->line
, buf
)) {
1476 #endif /* HAVE_WCHAR */
1477 for (i
= __virtscr
->maxx
;
1480 (void) memcpy(clp
->line
+ i
-
1481 BLANKSIZE
, buf
, sizeof(buf
));
1483 (void) memcpy(clp
->line
, buf
, i
*
1486 __CTRACE(__CTRACE_REFRESH
,
1487 " blanked out: dirty\n");
1489 clp
->hash
= blank_hash
;
1490 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1493 __CTRACE(__CTRACE_REFRESH
,
1494 " -- blank line already: dirty\n");
1496 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1500 __CTRACE(__CTRACE_REFRESH
, " -- dirty\n");
1502 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1504 if (target
== cur_period
) {
1506 tmp1
= curscr
->alines
[i
];
1514 __CTRACE(__CTRACE_REFRESH
, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
1515 for (i
= 0; i
< curscr
->maxy
; i
++) {
1516 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1517 for (j
= 0; j
< curscr
->maxx
; j
++)
1518 __CTRACE(__CTRACE_REFRESH
, "%c",
1519 curscr
->alines
[i
]->line
[j
].ch
);
1520 __CTRACE(__CTRACE_REFRESH
, "\n");
1521 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1522 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1523 __CTRACE(__CTRACE_REFRESH
, "%c",
1524 __virtscr
->alines
[i
]->line
[j
].ch
);
1525 __CTRACE(__CTRACE_REFRESH
, "\n");
1529 scrolln(starts
, startw
, curs
, bot
, top
);
1534 * Scroll n lines, where n is starts - startw.
1536 static void /* ARGSUSED */
1537 scrolln(starts
, startw
, curs
, bot
, top
)
1538 int starts
, startw
, curs
, bot
, top
;
1544 n
= starts
- startw
;
1548 * The initial tests that set __noqch don't let us reach here unless
1549 * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
1550 * scrolling can only shift the entire scrolling region, not just a
1551 * part of it, which means that the quickch() routine is going to be
1552 * sadly disappointed in us if we don't have cs as well.
1554 * If cs, ho and SF/sf are set, can use the scrolling region. Because
1555 * the cursor position after cs is undefined, we need ho which gives us
1556 * the ability to move to somewhere without knowledge of the current
1557 * location of the cursor. Still call __mvcur() anyway, to update its
1558 * idea of where the cursor is.
1560 * When the scrolling region has been set, the cursor has to be at the
1561 * last line of the region to make the scroll happen.
1563 * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr
1564 * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not
1565 * SF/SR. So, if we're scrolling almost all of the screen, try and use
1566 * AL/DL, otherwise use the scrolling region. The "almost all" is a
1567 * shameless hack for vi.
1570 if (change_scroll_region
!= NULL
&& cursor_home
!= NULL
&&
1571 (parm_index
!= NULL
||
1572 ((parm_insert_line
== NULL
|| parm_delete_line
== NULL
||
1573 top
> 3 || bot
+ 3 < __virtscr
->maxy
) &&
1574 scroll_forward
!= NULL
)))
1576 tputs(vtparm(change_scroll_region
, top
, bot
),
1578 __mvcur(oy
, ox
, 0, 0, 1);
1579 tputs(cursor_home
, 0, __cputchar
);
1580 __mvcur(0, 0, bot
, 0, 1);
1581 if (parm_index
!= NULL
)
1582 tputs(vtparm(parm_index
, n
),
1585 for (i
= 0; i
< n
; i
++)
1586 tputs(scroll_forward
, 0, __cputchar
);
1587 tputs(vtparm(change_scroll_region
,
1588 0, (int) __virtscr
->maxy
- 1), 0, __cputchar
);
1589 __mvcur(bot
, 0, 0, 0, 1);
1590 tputs(cursor_home
, 0, __cputchar
);
1591 __mvcur(0, 0, oy
, ox
, 1);
1595 /* Scroll up the block. */
1596 if (parm_index
!= NULL
&& top
== 0) {
1597 __mvcur(oy
, ox
, bot
, 0, 1);
1598 tputs(vtparm(parm_index
, n
), 0, __cputchar
);
1600 if (parm_delete_line
!= NULL
) {
1601 __mvcur(oy
, ox
, top
, 0, 1);
1602 tputs(vtparm(parm_delete_line
, n
),
1605 if (delete_line
!= NULL
) {
1606 __mvcur(oy
, ox
, top
, 0, 1);
1607 for (i
= 0; i
< n
; i
++)
1611 if (scroll_forward
!= NULL
&& top
== 0) {
1612 __mvcur(oy
, ox
, bot
, 0, 1);
1613 for (i
= 0; i
< n
; i
++)
1614 tputs(scroll_forward
, 0,
1619 /* Push down the bottom region. */
1620 __mvcur(top
, 0, bot
- n
+ 1, 0, 1);
1621 if (parm_insert_line
!= NULL
)
1622 tputs(vtparm(parm_insert_line
, n
), 0, __cputchar
);
1624 if (insert_line
!= NULL
)
1625 for (i
= 0; i
< n
; i
++)
1626 tputs(insert_line
, 0, __cputchar
);
1629 __mvcur(bot
- n
+ 1, 0, oy
, ox
, 1);
1635 * If cs, ho and SR/sr are set, can use the scrolling region.
1636 * See the above comments for details.
1638 if (change_scroll_region
!= NULL
&& cursor_home
!= NULL
&&
1639 (parm_rindex
!= NULL
||
1640 ((parm_insert_line
== NULL
|| parm_delete_line
== NULL
||
1642 bot
+ 3 < __virtscr
->maxy
) && scroll_reverse
!= NULL
)))
1644 tputs(vtparm(change_scroll_region
, top
, bot
),
1646 __mvcur(oy
, ox
, 0, 0, 1);
1647 tputs(cursor_home
, 0, __cputchar
);
1648 __mvcur(0, 0, top
, 0, 1);
1650 if (parm_rindex
!= NULL
)
1651 tputs(vtparm(parm_rindex
, -n
),
1654 for (i
= n
; i
< 0; i
++)
1655 tputs(scroll_reverse
, 0, __cputchar
);
1656 tputs(vtparm(change_scroll_region
,
1657 0, (int) __virtscr
->maxy
- 1), 0, __cputchar
);
1658 __mvcur(top
, 0, 0, 0, 1);
1659 tputs(cursor_home
, 0, __cputchar
);
1660 __mvcur(0, 0, oy
, ox
, 1);
1664 /* Preserve the bottom lines. */
1665 __mvcur(oy
, ox
, bot
+ n
+ 1, 0, 1);
1666 if (parm_rindex
!= NULL
&& bot
== __virtscr
->maxy
)
1667 tputs(vtparm(parm_rindex
, -n
), 0, __cputchar
);
1669 if (parm_delete_line
!= NULL
)
1670 tputs(vtparm(parm_delete_line
, -n
),
1673 if (delete_line
!= NULL
)
1674 for (i
= n
; i
< 0; i
++)
1678 if (scroll_reverse
!= NULL
&&
1679 bot
== __virtscr
->maxy
)
1680 for (i
= n
; i
< 0; i
++)
1681 tputs(scroll_reverse
, 0,
1686 /* Scroll the block down. */
1687 __mvcur(bot
+ n
+ 1, 0, top
, 0, 1);
1688 if (parm_insert_line
!= NULL
)
1689 tputs(vtparm(parm_insert_line
, -n
), 0, __cputchar
);
1691 if (insert_line
!= NULL
)
1692 for (i
= n
; i
< 0; i
++)
1693 tputs(insert_line
, 0, __cputchar
);
1696 __mvcur(top
, 0, oy
, ox
, 1);
1702 * Unset attributes on curscr. Leave standout, attribute and colour
1703 * modes if necessary (!ms). Always leave altcharset (xterm at least
1704 * ignores a cursor move if we don't).
1707 __unsetattr(int checkms
)
1712 if (!move_standout_mode
) {
1720 __CTRACE(__CTRACE_REFRESH
,
1721 "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n",
1722 checkms
, move_standout_mode
? "TRUE" : "FALSE", curscr
->wattr
);
1726 * Don't leave the screen in standout mode (check against ms). Check
1727 * to see if we also turn off underscore, attributes and colour.
1729 if (curscr
->wattr
& __STANDOUT
&& isms
) {
1730 tputs(exit_standout_mode
, 0, __cputchar
);
1731 curscr
->wattr
&= __mask_se
;
1734 * Don't leave the screen in underscore mode (check against ms).
1735 * Check to see if we also turn off attributes. Assume that we
1736 * also turn off colour.
1738 if (curscr
->wattr
& __UNDERSCORE
&& isms
) {
1739 tputs(exit_underline_mode
, 0, __cputchar
);
1740 curscr
->wattr
&= __mask_ue
;
1743 * Don't leave the screen with attributes set (check against ms).
1744 * Assume that also turn off colour.
1746 if (curscr
->wattr
& __TERMATTR
&& isms
) {
1747 tputs(exit_attribute_mode
, 0, __cputchar
);
1748 curscr
->wattr
&= __mask_me
;
1750 /* Don't leave the screen with altcharset set (don't check ms). */
1751 if (curscr
->wattr
& __ALTCHARSET
) {
1752 tputs(exit_alt_charset_mode
, 0, __cputchar
);
1753 curscr
->wattr
&= ~__ALTCHARSET
;
1755 /* Don't leave the screen with colour set (check against ms). */
1756 if (__using_color
&& isms
)
1757 __unset_color(curscr
);
1761 /* compare two cells on screen, must have the same forground/background,
1762 * and the same sequence of non-spacing characters */
1764 cellcmp( __LDATA
*x
, __LDATA
*y
)
1766 nschar_t
*xnp
= x
->nsp
, *ynp
= y
->nsp
;
1767 int ret
= ( x
->ch
== y
->ch
) & ( x
->attr
== y
->attr
);
1773 if (( xnp
&& !ynp
) || ( !xnp
&& ynp
))
1776 while ( xnp
&& ynp
) {
1777 if ( xnp
->ch
!= ynp
->ch
)
1782 return ( !xnp
&& !ynp
);
1785 /* compare two line segments */
1787 linecmp( __LDATA
*xl
, __LDATA
*yl
, size_t len
)
1790 __LDATA
*xp
= xl
, *yp
= yl
;
1792 for ( i
= 0; i
< len
; i
++, xp
++, yp
++ ) {
1793 if ( !cellcmp( xp
, yp
))
1800 * Output the non-spacing characters associated with the given character
1801 * cell to the screen.
1805 __cursesi_putnsp(nschar_t
*nsp
, const int wy
, const int wx
)
1809 /* this shuts up gcc warnings about wx and wy not being used */
1815 __cputwchar((int) p
->ch
);
1817 __CTRACE(__CTRACE_REFRESH
,
1818 "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n",
1825 #endif /* HAVE_WCHAR */