1 /* $NetBSD: refresh.c,v 1.77 2013/05/05 14:22:07 jdc 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.77 2013/05/05 14:22:07 jdc 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, "
236 "%d to %d, %d: %s, 0x%x",
237 wy
, wx
, y_off
, x_off
,
238 unctrl(wlp
->line
[wx
].ch
),
242 vlp
->line
[x_off
].ch
= wlp
->line
[wx
].ch
;
243 /* Copy attributes */
244 vlp
->line
[x_off
].attr
= wlp
->line
[wx
].attr
;
245 /* Check for nca conflict with colour */
246 if ((vlp
->line
[x_off
].attr
& __COLOR
) &&
247 (vlp
->line
[x_off
].attr
&
248 _cursesi_screen
->nca
))
249 vlp
->line
[x_off
].attr
&= ~__COLOR
;
252 == (wchar_t)btowc((int) win
->bch
)) {
253 vlp
->line
[x_off
].ch
= win
->bch
;
254 SET_WCOL( vlp
->line
[x_off
], 1 );
255 if (_cursesi_copy_nsp(win
->bnsp
,
260 #endif /* HAVE_WCHAR */
262 __CTRACE(__CTRACE_REFRESH
, " = %s, 0x%x\n",
263 unctrl(vlp
->line
[x_off
].ch
),
264 vlp
->line
[x_off
].attr
);
270 /* Set flags on "__virtscr" and unset on "win". */
271 if (wlp
->flags
& __ISPASTEOL
)
272 vlp
->flags
|= __ISPASTEOL
;
274 vlp
->flags
&= ~__ISPASTEOL
;
275 if (wlp
->flags
& __ISDIRTY
)
276 vlp
->flags
|= __ISDIRTY
;
279 __CTRACE(__CTRACE_REFRESH
,
280 "win: firstch = %d, lastch = %d\n",
281 *wlp
->firstchp
, *wlp
->lastchp
);
283 /* Set change pointers on "__virtscr". */
285 *wlp
->firstchp
+ wbegx
- win
->ch_off
)
287 *wlp
->firstchp
+ wbegx
- win
->ch_off
;
289 *wlp
->lastchp
+ wbegx
- win
->ch_off
)
291 *wlp
->lastchp
+ wbegx
- win
->ch_off
;
293 __CTRACE(__CTRACE_REFRESH
,
294 "__virtscr: firstch = %d, lastch = %d\n",
295 *vlp
->firstchp
, *vlp
->lastchp
);
298 * Unset change pointers only if a window, as a pad
299 * can be displayed again without any of the contents
302 if (!(win
->flags
& __ISPAD
)) {
303 /* Set change pointers on "win". */
304 if (*wlp
->firstchp
>= win
->ch_off
)
305 *wlp
->firstchp
= maxx
+ win
->ch_off
;
306 if (*wlp
->lastchp
< maxx
+ win
->ch_off
)
307 *wlp
->lastchp
= win
->ch_off
;
308 if ((*wlp
->lastchp
< *wlp
->firstchp
) ||
309 (*wlp
->firstchp
>= maxx
+ win
->ch_off
) ||
310 (*wlp
->lastchp
<= win
->ch_off
)) {
312 __CTRACE(__CTRACE_REFRESH
,
314 "line %d notdirty\n", wy
);
316 wlp
->flags
&= ~__ISDIRTY
;
326 * Make the current screen look like "win" over the area covered by
330 wrefresh(WINDOW
*win
)
335 __CTRACE(__CTRACE_REFRESH
, "wrefresh: win %p\n", win
);
338 _cursesi_screen
->curwin
= (win
== _cursesi_screen
->curscr
);
339 if (!_cursesi_screen
->curwin
)
340 retval
= _cursesi_wnoutrefresh(_cursesi_screen
, win
, 0, 0,
341 win
->begy
, win
->begx
, win
->maxy
, win
->maxx
);
346 if (!(win
->flags
& __LEAVEOK
)) {
347 win
->cury
= max(0, curscr
->cury
- win
->begy
);
348 win
->curx
= max(0, curscr
->curx
- win
->begx
);
351 _cursesi_screen
->curwin
= 0;
357 * Make the current screen look like "pad" over the area coverd by
358 * the specified area of pad.
361 prefresh(WINDOW
*pad
, int pbegy
, int pbegx
, int sbegy
, int sbegx
,
362 int smaxy
, int smaxx
)
367 __CTRACE(__CTRACE_REFRESH
, "prefresh: pad %p, flags 0x%08x\n",
370 /* Retain values in case pechochar() is called. */
378 /* Use pnoutrefresh() to avoid duplicating code here */
379 retval
= pnoutrefresh(pad
, pbegy
, pbegx
, sbegy
, sbegx
, smaxy
, smaxx
);
382 if (!(pad
->flags
& __LEAVEOK
)) {
383 pad
->cury
= max(0, curscr
->cury
- pad
->begy
);
384 pad
->curx
= max(0, curscr
->curx
- pad
->begx
);
392 * Make the current screen look like the virtual window "__virtscr".
405 #endif /* HAVE_WCHAR */
407 /* Check if we need to restart ... */
408 if (_cursesi_screen
->endwin
)
411 if (_cursesi_screen
->curwin
)
414 win
= _cursesi_screen
->__virtscr
;
416 /* Initialize loop parameters. */
417 _cursesi_screen
->ly
= curscr
->cury
;
418 _cursesi_screen
->lx
= curscr
->curx
;
421 if (!_cursesi_screen
->curwin
) {
422 for (wy
= 0; wy
< win
->maxy
; wy
++) {
423 wlp
= win
->alines
[wy
];
424 if (wlp
->flags
& __ISDIRTY
) {
426 wlp
->hash
= __hash(wlp
->line
,
427 (size_t)(win
->maxx
* __LDATASIZE
));
430 for ( x
= 0; x
< win
->maxx
; x
++ ) {
431 lp
= &wlp
->line
[ x
];
432 wlp
->hash
= __hash_more( &lp
->ch
,
433 sizeof( wchar_t ), wlp
->hash
);
434 wlp
->hash
= __hash_more( &lp
->attr
,
435 sizeof( attr_t
), wlp
->hash
);
448 #endif /* HAVE_WCHAR */
453 if ((win
->flags
& __CLEAROK
) || (curscr
->flags
& __CLEAROK
) ||
454 _cursesi_screen
->curwin
) {
455 if (curscr
->wattr
& __COLOR
)
457 tputs(clear_screen
, 0, __cputchar
);
458 _cursesi_screen
->ly
= 0;
459 _cursesi_screen
->lx
= 0;
460 if (!_cursesi_screen
->curwin
) {
461 curscr
->flags
&= ~__CLEAROK
;
467 win
->flags
&= ~__CLEAROK
;
469 if (!cursor_address
) {
472 if (!_cursesi_screen
->curwin
)
476 __CTRACE(__CTRACE_REFRESH
, "doupdate: (%p): curwin = %d\n", win
,
477 _cursesi_screen
->curwin
);
478 __CTRACE(__CTRACE_REFRESH
, "doupdate: \tfirstch\tlastch\n");
481 if (!_cursesi_screen
->curwin
) {
483 * Invoke quickch() only if more than a quarter of the lines
484 * in the window are dirty.
486 for (wy
= 0, dnum
= 0; wy
< win
->maxy
; wy
++)
487 if (win
->alines
[wy
]->flags
& __ISDIRTY
)
489 if (!__noqch
&& dnum
> (int) win
->maxy
/ 4)
497 __CTRACE(__CTRACE_REFRESH
,
498 "#####################################\n");
499 __CTRACE(__CTRACE_REFRESH
,
500 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
501 stdscr
, curscr
, _cursesi_screen
->__virtscr
);
502 for (i
= 0; i
< curscr
->maxy
; i
++) {
503 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
504 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
505 curscr
->alines
[i
]->hash
);
506 for (j
= 0; j
< curscr
->maxx
; j
++)
507 __CTRACE(__CTRACE_REFRESH
, "%c",
508 curscr
->alines
[i
]->line
[j
].ch
);
509 __CTRACE(__CTRACE_REFRESH
, "\n");
510 __CTRACE(__CTRACE_REFRESH
, " attr:");
511 for (j
= 0; j
< curscr
->maxx
; j
++)
512 __CTRACE(__CTRACE_REFRESH
, " %x",
513 curscr
->alines
[i
]->line
[j
].attr
);
514 __CTRACE(__CTRACE_REFRESH
, "\n");
515 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
516 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
517 win
->alines
[i
]->hash
);
518 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
519 win
->alines
[i
]->flags
);
520 for (j
= 0; j
< win
->maxx
; j
++)
521 __CTRACE(__CTRACE_REFRESH
, "%c",
522 win
->alines
[i
]->line
[j
].ch
);
523 __CTRACE(__CTRACE_REFRESH
, "\n");
524 __CTRACE(__CTRACE_REFRESH
, " attr:");
525 for (j
= 0; j
< win
->maxx
; j
++)
526 __CTRACE(__CTRACE_REFRESH
, " %x",
527 win
->alines
[i
]->line
[j
].attr
);
528 __CTRACE(__CTRACE_REFRESH
, "\n");
530 __CTRACE(__CTRACE_REFRESH
, " nsp:");
531 for (j
= 0; j
< curscr
->maxx
; j
++)
532 __CTRACE(__CTRACE_REFRESH
, " %p",
533 win
->alines
[i
]->line
[j
].nsp
);
534 __CTRACE(__CTRACE_REFRESH
, "\n");
535 __CTRACE(__CTRACE_REFRESH
, " bnsp:");
536 for (j
= 0; j
< curscr
->maxx
; j
++)
537 __CTRACE(__CTRACE_REFRESH
, " %p",
539 __CTRACE(__CTRACE_REFRESH
, "\n");
540 #endif /* HAVE_WCHAR */
545 for (wy
= 0; wy
< win
->maxy
; wy
++) {
546 wlp
= win
->alines
[wy
];
547 /* XXX: remove this debug */
549 __CTRACE(__CTRACE_REFRESH
,
550 "doupdate: wy %d\tf: %d\tl:%d\tflags %x\n",
551 wy
, *wlp
->firstchp
, *wlp
->lastchp
, wlp
->flags
);
553 if (!_cursesi_screen
->curwin
)
554 curscr
->alines
[wy
]->hash
= wlp
->hash
;
555 if (wlp
->flags
& __ISDIRTY
) {
557 __CTRACE(__CTRACE_REFRESH
,
558 "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy
,
559 *wlp
->firstchp
, *wlp
->lastchp
);
561 if (makech(wy
) == ERR
)
564 if (*wlp
->firstchp
>= 0)
565 *wlp
->firstchp
= win
->maxx
;
566 if (*wlp
->lastchp
< win
->maxx
)
568 if (*wlp
->lastchp
< *wlp
->firstchp
) {
570 __CTRACE(__CTRACE_REFRESH
,
571 "doupdate: line %d notdirty\n", wy
);
573 wlp
->flags
&= ~__ISDIRTY
;
579 __CTRACE(__CTRACE_REFRESH
, "\t%d\t%d\n",
580 *wlp
->firstchp
, *wlp
->lastchp
);
585 __CTRACE(__CTRACE_REFRESH
, "doupdate: ly=%d, lx=%d\n",
586 _cursesi_screen
->ly
, _cursesi_screen
->lx
);
589 if (_cursesi_screen
->curwin
)
590 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
591 win
->cury
, win
->curx
);
593 if (win
->flags
& __LEAVEOK
) {
594 curscr
->cury
= _cursesi_screen
->ly
;
595 curscr
->curx
= _cursesi_screen
->lx
;
597 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
598 win
->cury
, win
->curx
);
599 curscr
->cury
= win
->cury
;
600 curscr
->curx
= win
->curx
;
604 /* Don't leave the screen with attributes set. */
611 __CTRACE(__CTRACE_REFRESH
,
612 "***********after*****************\n");
613 __CTRACE(__CTRACE_REFRESH
,
614 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
615 stdscr
, curscr
, _cursesi_screen
->__virtscr
);
616 for (i
= 0; i
< curscr
->maxy
; i
++) {
617 for (j
= 0; j
< curscr
->maxx
; j
++)
618 __CTRACE(__CTRACE_REFRESH
,
619 "[%d,%d](%x,%x,%p)-(%x,%x,%p)\n",
621 curscr
->alines
[i
]->line
[j
].ch
,
622 curscr
->alines
[i
]->line
[j
].attr
,
623 curscr
->alines
[i
]->line
[j
].nsp
,
624 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].ch
,
625 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].attr
,
626 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].nsp
);
629 #endif /* HAVE_WCHAR */
631 return fflush(_cursesi_screen
->outfd
) == EOF
? ERR
: OK
;
636 * Make a change on the screen.
642 static __LDATA blank
;
643 __LDATA
*nsp
, *csp
, *cp
, *cep
;
644 size_t clsp
, nlsp
; /* Last space in lines. */
647 attr_t lspc
; /* Last space colour */
651 nlsp
= lspc
= 0; /* XXX gcc -Wuninitialized */
653 if (_cursesi_screen
->curwin
)
658 blank
.ch
= ( wchar_t )btowc(( int ) win
->bch
);
660 if (_cursesi_copy_nsp(win
->bnsp
, &blank
) == ERR
)
662 SET_WCOL( blank
, 1 );
663 #endif /* HAVE_WCHAR */
670 __CTRACE(__CTRACE_REFRESH
,
671 "[makech-before]wy=%d,curscr(%p)-__virtscr(%p)\n",
672 wy
, curscr
, __virtscr
);
673 for (x
= 0; x
< curscr
->maxx
; x
++) {
674 lp
= &curscr
->alines
[wy
]->line
[x
];
675 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
676 __CTRACE(__CTRACE_REFRESH
,
677 "[%d,%d](%x,%x,%x,%x,%p)-"
678 "(%x,%x,%x,%x,%p)\n",
679 wy
, x
, lp
->ch
, lp
->attr
,
680 win
->bch
, win
->battr
, lp
->nsp
,
682 win
->bch
, win
->battr
, vlp
->nsp
);
685 #endif /* HAVE_WCHAR */
687 /* Is the cursor still on the end of the last line? */
688 if (wy
> 0 && curscr
->alines
[wy
- 1]->flags
& __ISPASTEOL
) {
689 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
690 _cursesi_screen
->ly
+ 1, 0);
691 _cursesi_screen
->ly
++;
692 _cursesi_screen
->lx
= 0;
694 wx
= *win
->alines
[wy
]->firstchp
;
700 lch
= *win
->alines
[wy
]->lastchp
;
704 if (lch
>= (int) win
->maxx
)
707 if (_cursesi_screen
->curwin
) {
710 __CTRACE(__CTRACE_REFRESH
, "makech: csp is blank\n");
713 csp
= &curscr
->alines
[wy
]->line
[wx
];
715 __CTRACE(__CTRACE_REFRESH
,
716 "makech: csp is on curscr:(%d,%d)\n", wy
, wx
);
720 nsp
= &win
->alines
[wy
]->line
[wx
];
722 if ( _cursesi_screen
->curwin
)
723 __CTRACE(__CTRACE_REFRESH
,
724 "makech: nsp is at curscr:(%d,%d)\n", wy
, wx
);
726 __CTRACE(__CTRACE_REFRESH
,
727 "makech: nsp is at __virtscr:(%d,%d)\n", wy
, wx
);
729 if (clr_eol
&& !_cursesi_screen
->curwin
) {
730 cp
= &win
->alines
[wy
]->line
[win
->maxx
- 1];
731 lspc
= cp
->attr
& __COLOR
;
733 while (cp
->ch
== ' ' && cp
->attr
== lspc
) /* XXX */
734 if (cp
-- <= win
->alines
[wy
]->line
)
737 while (cp
->ch
== ( wchar_t )btowc(( int )' ' )
738 && ( cp
->attr
& WA_ATTRIBUTES
) == lspc
)
739 if (cp
-- <= win
->alines
[wy
]->line
)
741 #endif /* HAVE_WCHAR */
742 if (win
->alines
[wy
]->line
> cp
)
745 nlsp
= cp
- win
->alines
[wy
]->line
;
747 if (!_cursesi_screen
->curwin
)
754 __CTRACE(__CTRACE_REFRESH
, "makech: wx=%d,lch=%d\n", wx
, lch
);
757 if (memcmp(nsp
, csp
, sizeof(__LDATA
)) == 0) {
760 memcmp(nsp
, csp
, sizeof(__LDATA
)) == 0) {
762 if (!_cursesi_screen
->curwin
)
772 __CTRACE(__CTRACE_REFRESH
, "makech: nsp=(%x,%x,%x,%x,%p)\n",
773 nsp
->ch
, nsp
->attr
, win
->bch
, win
->battr
, nsp
->nsp
);
774 __CTRACE(__CTRACE_REFRESH
, "makech: csp=(%x,%x,%x,%x,%p)\n",
775 csp
->ch
, csp
->attr
, win
->bch
, win
->battr
, csp
->nsp
);
777 if (((nsp
->attr
& __WCWIDTH
) != __WCWIDTH
) &&
780 while (wx
<= lch
&& cellcmp( csp
, nsp
)) {
782 if (!_cursesi_screen
->curwin
)
790 #endif /* HAVE_WCHAR */
791 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
, wy
, wx
);
794 __CTRACE(__CTRACE_REFRESH
, "makech: 1: wx = %d, ly= %d, "
795 "lx = %d, newy = %d, newx = %d\n",
796 wx
, _cursesi_screen
->ly
, _cursesi_screen
->lx
, wy
, wx
);
798 _cursesi_screen
->ly
= wy
;
799 _cursesi_screen
->lx
= wx
;
801 while (wx
<= lch
&& memcmp(nsp
, csp
, sizeof(__LDATA
)) != 0) {
803 wx
>= nlsp
&& nsp
->ch
== ' ' && nsp
->attr
== lspc
) {
805 while (!cellcmp(nsp
, csp
) && wx
<= lch
) {
806 if (ce
!= NULL
&& wx
>= nlsp
807 && nsp
->ch
== (wchar_t)btowc((int)' ') /* XXX */
808 && (nsp
->attr
& WA_ATTRIBUTES
) == lspc
) {
811 /* Check for clear to end-of-line. */
812 cep
= &curscr
->alines
[wy
]->line
[win
->maxx
- 1];
814 while (cep
->ch
== ' ' && cep
->attr
== lspc
) /* XXX */
816 while (cep
->ch
== (wchar_t)btowc((int)' ')
817 && (cep
->attr
& WA_ATTRIBUTES
) == lspc
)
818 #endif /* HAVE_WCHAR */
821 clsp
= cep
- curscr
->alines
[wy
]->line
-
822 win
->begx
* __LDATASIZE
;
824 __CTRACE(__CTRACE_REFRESH
,
825 "makech: clsp = %zu, nlsp = %zu\n",
828 if (((clsp
- nlsp
>= strlen(clr_eol
) &&
829 clsp
< win
->maxx
* __LDATASIZE
) ||
830 wy
== win
->maxy
- 1) &&
831 (!(lspc
& __COLOR
) ||
832 ((lspc
& __COLOR
) && back_color_erase
))) {
836 (curscr
->wattr
& __COLOR
)))
837 __set_color(curscr
, lspc
&
839 tputs(clr_eol
, 0, __cputchar
);
840 _cursesi_screen
->lx
= wx
+ win
->begx
;
841 while (wx
++ <= clsp
) {
844 csp
->ch
= ' '; /* XXX */
846 csp
->ch
= (wchar_t)btowc((int)' ');
848 #endif /* HAVE_WCHAR */
857 __CTRACE(__CTRACE_REFRESH
,
858 "makech: have attr %08x, need attr %08x\n",
874 off
= (~nsp
->attr
& curscr
->wattr
)
883 * Unset attributes as appropriate. Unset first
884 * so that the relevant attributes can be reset
885 * (because 'me' unsets 'mb', 'md', 'mh', 'mk',
886 * 'mp' and 'mr'). Check to see if we also turn off
887 * standout, attributes and colour.
889 if (off
& __TERMATTR
&& exit_attribute_mode
!= NULL
) {
890 tputs(exit_attribute_mode
, 0, __cputchar
);
891 curscr
->wattr
&= __mask_me
;
896 * Exit underscore mode if appropriate.
897 * Check to see if we also turn off standout,
898 * attributes and colour.
900 if (off
& __UNDERSCORE
&& exit_underline_mode
!= NULL
) {
901 tputs(exit_underline_mode
, 0, __cputchar
);
902 curscr
->wattr
&= __mask_ue
;
907 * Exit standout mode as appropriate.
908 * Check to see if we also turn off underscore,
909 * attributes and colour.
911 * Should use uc if so/se not available.
913 if (off
& __STANDOUT
&& exit_standout_mode
!= NULL
) {
914 tputs(exit_standout_mode
, 0, __cputchar
);
915 curscr
->wattr
&= __mask_se
;
919 if (off
& __ALTCHARSET
&& exit_alt_charset_mode
!= NULL
) {
920 tputs(exit_alt_charset_mode
, 0, __cputchar
);
921 curscr
->wattr
&= ~__ALTCHARSET
;
924 /* Set/change colour as appropriate. */
926 __set_color(curscr
, nsp
->attr
& __COLOR
);
928 on
= (nsp
->attr
& ~curscr
->wattr
)
937 * Enter standout mode if appropriate.
939 if (on
& __STANDOUT
&&
940 enter_standout_mode
!= NULL
&&
941 exit_standout_mode
!= NULL
)
943 tputs(enter_standout_mode
, 0, __cputchar
);
944 curscr
->wattr
|= __STANDOUT
;
948 * Enter underscore mode if appropriate.
950 * Should use uc if us/ue not available.
952 if (on
& __UNDERSCORE
&&
953 enter_underline_mode
!= NULL
&&
954 exit_underline_mode
!= NULL
)
956 tputs(enter_underline_mode
, 0, __cputchar
);
957 curscr
->wattr
|= __UNDERSCORE
;
961 * Set other attributes as appropriate.
963 if (exit_attribute_mode
!= NULL
) {
965 enter_blink_mode
!= NULL
)
967 tputs(enter_blink_mode
, 0, __cputchar
);
968 curscr
->wattr
|= __BLINK
;
971 enter_bold_mode
!= NULL
)
973 tputs(enter_bold_mode
, 0, __cputchar
);
974 curscr
->wattr
|= __BOLD
;
977 enter_dim_mode
!= NULL
)
979 tputs(enter_dim_mode
, 0, __cputchar
);
980 curscr
->wattr
|= __DIM
;
983 enter_secure_mode
!= NULL
)
985 tputs(enter_secure_mode
, 0, __cputchar
);
986 curscr
->wattr
|= __BLANK
;
988 if (on
& __PROTECT
&&
989 enter_protected_mode
!= NULL
)
991 tputs(enter_protected_mode
, 0, __cputchar
);
992 curscr
->wattr
|= __PROTECT
;
994 if (on
& __REVERSE
&&
995 enter_reverse_mode
!= NULL
)
997 tputs(enter_reverse_mode
, 0, __cputchar
);
998 curscr
->wattr
|= __REVERSE
;
1002 enter_top_hl_mode
!= NULL
)
1004 tputs(enter_top_hl_mode
, 0, __cputchar
);
1005 curscr
->wattr
|= WA_TOP
;
1008 enter_low_hl_mode
!= NULL
)
1010 tputs(enter_low_hl_mode
, 0, __cputchar
);
1011 curscr
->wattr
|= WA_LOW
;
1014 enter_left_hl_mode
!= NULL
)
1016 tputs(enter_left_hl_mode
, 0, __cputchar
);
1017 curscr
->wattr
|= WA_LEFT
;
1019 if (on
& WA_RIGHT
&&
1020 enter_right_hl_mode
!= NULL
)
1022 tputs(enter_right_hl_mode
, 0, __cputchar
);
1023 curscr
->wattr
|= WA_RIGHT
;
1025 if (on
& WA_HORIZONTAL
&&
1026 enter_horizontal_hl_mode
!= NULL
)
1028 tputs(enter_horizontal_hl_mode
, 0, __cputchar
);
1029 curscr
->wattr
|= WA_HORIZONTAL
;
1031 if (on
& WA_VERTICAL
&&
1032 enter_vertical_hl_mode
!= NULL
)
1034 tputs(enter_vertical_hl_mode
, 0, __cputchar
);
1035 curscr
->wattr
|= WA_VERTICAL
;
1037 #endif /* HAVE_WCHAR */
1040 /* Enter/exit altcharset mode as appropriate. */
1041 if (on
& __ALTCHARSET
&& enter_alt_charset_mode
!= NULL
&&
1042 exit_alt_charset_mode
!= NULL
) {
1043 tputs(enter_alt_charset_mode
, 0, __cputchar
);
1044 curscr
->wattr
|= __ALTCHARSET
;
1048 if (wx
>= win
->maxx
&&
1049 wy
== win
->maxy
- 1 && !_cursesi_screen
->curwin
) {
1050 if (win
->flags
& __SCROLLOK
) {
1051 if (win
->flags
& __ENDLINE
)
1053 if (!(win
->flags
& __SCROLLWIN
)) {
1054 if (!_cursesi_screen
->curwin
) {
1055 csp
->attr
= nsp
->attr
;
1058 if (_cursesi_copy_nsp(nsp
->nsp
, csp
) == ERR
)
1060 #endif /* HAVE_WCHAR */
1063 __cputchar((int) nsp
->ch
);
1065 if ( WCOL( *nsp
) > 0 ) {
1066 __cputwchar((int)nsp
->ch
);
1068 __CTRACE(__CTRACE_REFRESH
,
1069 "makech: (%d,%d)putwchar(0x%x)\n",
1074 * Output non-spacing
1075 * characters for the
1078 __cursesi_putnsp(nsp
->nsp
,
1082 #endif /* HAVE_WCHAR */
1084 if (wx
< curscr
->maxx
) {
1085 domvcur(_cursesi_screen
->ly
, wx
,
1086 (int) (win
->maxy
- 1),
1087 (int) (win
->maxx
- 1));
1089 _cursesi_screen
->ly
= win
->maxy
- 1;
1090 _cursesi_screen
->lx
= win
->maxx
- 1;
1094 if (wx
< win
->maxx
|| wy
< win
->maxy
- 1 ||
1095 !(win
->flags
& __SCROLLWIN
)) {
1096 if (!_cursesi_screen
->curwin
) {
1097 csp
->attr
= nsp
->attr
;
1100 if (_cursesi_copy_nsp(nsp
->nsp
,
1103 #endif /* HAVE_WCHAR */
1107 __cputchar((int) nsp
->ch
);
1109 __CTRACE(__CTRACE_REFRESH
,
1110 "makech: putchar(%c)\n", nsp
->ch
& 0177);
1113 if (WCOL(*nsp
) > 0) {
1114 __cputwchar((int) nsp
->ch
);
1116 __CTRACE(__CTRACE_REFRESH
,
1117 "makech:(%d,%d) putwchar(%x)\n",
1118 wy
, wx
- 1, nsp
->ch
);
1119 __cursesi_putnsp(nsp
->nsp
, wy
, wx
);
1122 #endif /* HAVE_WCHAR */
1124 if (underline_char
&& ((nsp
->attr
& __STANDOUT
) ||
1125 (nsp
->attr
& __UNDERSCORE
))) {
1127 tputs(underline_char
, 0, __cputchar
);
1131 __CTRACE(__CTRACE_REFRESH
,
1132 "makech: 2: wx = %d, lx = %d\n",
1133 wx
, _cursesi_screen
->lx
);
1136 if (_cursesi_screen
->lx
== wx
) /* If no change. */
1138 _cursesi_screen
->lx
= wx
;
1139 if (_cursesi_screen
->lx
>= COLS
&& auto_right_margin
)
1140 _cursesi_screen
->lx
= COLS
- 1;
1142 if (wx
>= win
->maxx
) {
1143 domvcur(_cursesi_screen
->ly
,
1144 _cursesi_screen
->lx
,
1145 _cursesi_screen
->ly
,
1146 (int) (win
->maxx
- 1));
1147 _cursesi_screen
->lx
= win
->maxx
- 1;
1150 __CTRACE(__CTRACE_REFRESH
, "makech: 3: wx = %d, lx = %d\n",
1151 wx
, _cursesi_screen
->lx
);
1160 __CTRACE(__CTRACE_REFRESH
,
1161 "makech-after: curscr(%p)-__virtscr(%p)\n",
1162 curscr
, __virtscr
);
1163 for (x
= 0; x
< curscr
->maxx
; x
++) {
1164 lp
= &curscr
->alines
[wy
]->line
[x
];
1165 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
1166 __CTRACE(__CTRACE_REFRESH
,
1167 "[%d,%d](%x,%x,%x,%x,%p)-"
1168 "(%x,%x,%x,%x,%p)\n",
1169 wy
, x
, lp
->ch
, lp
->attr
,
1170 win
->bch
, win
->battr
, lp
->nsp
,
1172 win
->bch
, win
->battr
, vlp
->nsp
);
1175 #endif /* HAVE_WCHAR */
1183 * Do a mvcur, leaving attributes if necessary.
1186 domvcur(oy
, ox
, ny
, nx
)
1190 __CTRACE(__CTRACE_REFRESH
, "domvcur: (%x,%d)=>(%d,%d)\n",
1194 if ( oy
== ny
&& ox
== nx
)
1196 __mvcur(oy
, ox
, ny
, nx
, 1);
1200 * Quickch() attempts to detect a pattern in the change of the window
1201 * in order to optimize the change, e.g., scroll n lines as opposed to
1202 * repainting the screen line by line.
1205 static __LDATA buf
[128];
1206 static u_int last_hash
;
1207 static size_t last_hash_len
;
1208 #define BLANKSIZE (sizeof(buf) / sizeof(buf[0]))
1213 #define THRESH (int) __virtscr->maxy / 4
1215 __LINE
*clp
, *tmp1
, *tmp2
;
1216 int bsize
, curs
, curw
, starts
, startw
, i
, j
;
1217 int n
, target
, cur_period
, bot
, top
, sc_region
;
1222 curs
= curw
= starts
= startw
= 0; /* XXX gcc -Wuninitialized */
1225 * Find how many lines from the top of the screen are unchanged.
1227 for (top
= 0; top
< __virtscr
->maxy
; top
++)
1229 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1230 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1231 memcmp(__virtscr
->alines
[top
]->line
,
1232 curscr
->alines
[top
]->line
,
1233 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1237 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1238 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1239 !linecmp(__virtscr
->alines
[top
]->line
,
1240 curscr
->alines
[top
]->line
,
1241 (size_t) __virtscr
->maxx
)))
1243 #endif /* HAVE_WCHAR */
1245 __virtscr
->alines
[top
]->flags
&= ~__ISDIRTY
;
1247 * Find how many lines from bottom of screen are unchanged.
1249 for (bot
= __virtscr
->maxy
- 1; bot
>= 0; bot
--)
1251 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1252 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1253 memcmp(__virtscr
->alines
[bot
]->line
,
1254 curscr
->alines
[bot
]->line
,
1255 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1259 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1260 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1261 !linecmp(__virtscr
->alines
[bot
]->line
,
1262 curscr
->alines
[bot
]->line
,
1263 (size_t) __virtscr
->maxx
)))
1265 #endif /* HAVE_WCHAR */
1267 __virtscr
->alines
[bot
]->flags
&= ~__ISDIRTY
;
1270 * Work round an xterm bug where inserting lines causes all the
1271 * inserted lines to be covered with the background colour we
1272 * set on the first line (even if we unset it for subsequent
1275 bcolor
= __virtscr
->alines
[min(top
,
1276 __virtscr
->maxy
- 1)]->line
[0].attr
& __COLOR
;
1277 for (i
= top
+ 1, j
= 0; i
< bot
; i
++) {
1278 if ((__virtscr
->alines
[i
]->line
[0].attr
& __COLOR
) != bcolor
) {
1279 bcolor
= __virtscr
->alines
[i
]->line
[__virtscr
->maxx
].
1289 * If we have a bottom unchanged region return. Scrolling the
1290 * bottom region up and then back down causes a screen jitter.
1291 * This will increase the number of characters sent to the screen
1292 * but it looks better.
1294 if (bot
< __virtscr
->maxy
- 1)
1296 #endif /* NO_JERKINESS */
1299 * Search for the largest block of text not changed.
1300 * Invariants of the loop:
1301 * - Startw is the index of the beginning of the examined block in
1303 * - Starts is the index of the beginning of the examined block in
1305 * - Curw is the index of one past the end of the exmined block in
1307 * - Curs is the index of one past the end of the exmined block in
1309 * - bsize is the current size of the examined block.
1312 for (bsize
= bot
- top
; bsize
>= THRESH
; bsize
--) {
1313 for (startw
= top
; startw
<= bot
- bsize
; startw
++)
1314 for (starts
= top
; starts
<= bot
- bsize
;
1316 for (curw
= startw
, curs
= starts
;
1317 curs
< starts
+ bsize
; curw
++, curs
++)
1318 if (__virtscr
->alines
[curw
]->hash
!=
1319 curscr
->alines
[curs
]->hash
)
1321 if (curs
!= starts
+ bsize
)
1323 for (curw
= startw
, curs
= starts
;
1324 curs
< starts
+ bsize
; curw
++, curs
++)
1326 if (memcmp(__virtscr
->alines
[curw
]->line
,
1327 curscr
->alines
[curs
]->line
,
1328 (size_t) __virtscr
->maxx
*
1332 if (!linecmp(__virtscr
->alines
[curw
]->line
,
1333 curscr
->alines
[curs
]->line
,
1334 (size_t) __virtscr
->maxx
))
1336 #endif /* HAVE_WCHAR */
1337 if (curs
== starts
+ bsize
)
1343 /* Did not find anything */
1348 __CTRACE(__CTRACE_REFRESH
, "quickch:bsize=%d, starts=%d, startw=%d, "
1349 "curw=%d, curs=%d, top=%d, bot=%d\n",
1350 bsize
, starts
, startw
, curw
, curs
, top
, bot
);
1354 * Make sure that there is no overlap between the bottom and top
1355 * regions and the middle scrolled block.
1362 n
= startw
- starts
;
1365 __CTRACE(__CTRACE_REFRESH
, "#####################################\n");
1366 for (i
= 0; i
< curscr
->maxy
; i
++) {
1367 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1368 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n", curscr
->alines
[i
]->hash
);
1369 for (j
= 0; j
< curscr
->maxx
; j
++)
1370 __CTRACE(__CTRACE_REFRESH
, "%c",
1371 curscr
->alines
[i
]->line
[j
].ch
);
1372 __CTRACE(__CTRACE_REFRESH
, "\n");
1373 __CTRACE(__CTRACE_REFRESH
, " attr:");
1374 for (j
= 0; j
< curscr
->maxx
; j
++)
1375 __CTRACE(__CTRACE_REFRESH
, " %x",
1376 curscr
->alines
[i
]->line
[j
].attr
);
1377 __CTRACE(__CTRACE_REFRESH
, "\n");
1378 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1379 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
1380 __virtscr
->alines
[i
]->hash
);
1381 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
1382 __virtscr
->alines
[i
]->flags
);
1383 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1384 __CTRACE(__CTRACE_REFRESH
, "%c",
1385 __virtscr
->alines
[i
]->line
[j
].ch
);
1386 __CTRACE(__CTRACE_REFRESH
, "\n");
1387 __CTRACE(__CTRACE_REFRESH
, " attr:");
1388 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1389 __CTRACE(__CTRACE_REFRESH
, " %x",
1390 __virtscr
->alines
[i
]->line
[j
].attr
);
1391 __CTRACE(__CTRACE_REFRESH
, "\n");
1396 if (buf
[0].ch
!= ' ') {
1397 for (i
= 0; i
< BLANKSIZE
; i
++) {
1403 if (buf
[0].ch
!= ( wchar_t )btowc(( int ) curscr
->bch
)) {
1404 for (i
= 0; i
< BLANKSIZE
; i
++) {
1405 buf
[i
].ch
= ( wchar_t )btowc(( int ) curscr
->bch
);
1406 if (_cursesi_copy_nsp(curscr
->bnsp
, &buf
[i
]) == ERR
)
1409 SET_WCOL( buf
[ i
], 1 );
1412 #endif /* HAVE_WCHAR */
1414 if (__virtscr
->maxx
!= last_hash_len
) {
1416 for (i
= __virtscr
->maxx
; i
> BLANKSIZE
; i
-= BLANKSIZE
) {
1417 blank_hash
= __hash_more(buf
, sizeof(buf
), blank_hash
);
1419 blank_hash
= __hash_more((char *)(void *)buf
,
1420 i
* sizeof(buf
[0]), blank_hash
);
1421 /* cache result in static data - screen width doesn't change often */
1422 last_hash_len
= __virtscr
->maxx
;
1423 last_hash
= blank_hash
;
1425 blank_hash
= last_hash
;
1428 * Perform the rotation to maintain the consistency of curscr.
1429 * This is hairy since we are doing an *in place* rotation.
1430 * Invariants of the loop:
1431 * - I is the index of the current line.
1432 * - Target is the index of the target of line i.
1433 * - Tmp1 points to current line (i).
1434 * - Tmp2 and points to target line (target);
1435 * - Cur_period is the index of the end of the current period.
1438 * There are 2 major issues here that make this rotation non-trivial:
1439 * 1. Scrolling in a scrolling region bounded by the top
1440 * and bottom regions determined (whose size is sc_region).
1441 * 2. As a result of the use of the mod function, there may be a
1442 * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
1443 * 0 to 2, which then causes all odd lines not to be rotated.
1444 * To remedy this, an index of the end ( = beginning) of the
1445 * current 'period' is kept, cur_period, and when it is reached,
1446 * the next period is started from cur_period + 1 which is
1447 * guaranteed not to have been reached since that would mean that
1448 * all records would have been reached. (think about it...).
1450 * Lines in the rotation can have 3 attributes which are marked on the
1451 * line so that curscr is consistent with the visual screen.
1452 * 1. Not dirty -- lines inside the scrolled block, top region or
1454 * 2. Blank lines -- lines in the differential of the scrolling
1455 * region adjacent to top and bot regions
1456 * depending on scrolling direction.
1457 * 3. Dirty line -- all other lines are marked dirty.
1459 sc_region
= bot
- top
+ 1;
1461 tmp1
= curscr
->alines
[top
];
1463 for (j
= top
; j
<= bot
; j
++) {
1464 target
= (i
- top
+ n
+ sc_region
) % sc_region
+ top
;
1465 tmp2
= curscr
->alines
[target
];
1466 curscr
->alines
[target
] = tmp1
;
1467 /* Mark block as clean and blank out scrolled lines. */
1468 clp
= curscr
->alines
[target
];
1470 __CTRACE(__CTRACE_REFRESH
,
1471 "quickch: n=%d startw=%d curw=%d i = %d target=%d ",
1472 n
, startw
, curw
, i
, target
);
1474 if ((target
>= startw
&& target
< curw
) || target
< top
1477 __CTRACE(__CTRACE_REFRESH
, " notdirty\n");
1479 __virtscr
->alines
[target
]->flags
&= ~__ISDIRTY
;
1481 if ((n
> 0 && target
>= top
&& target
< top
+ n
) ||
1482 (n
< 0 && target
<= bot
&& target
> bot
+ n
)) {
1484 if (clp
->hash
!= blank_hash
||
1485 memcmp(clp
->line
, clp
->line
+ 1,
1486 (__virtscr
->maxx
- 1)
1488 memcmp(clp
->line
, buf
, __LDATASIZE
)) {
1490 if (clp
->hash
!= blank_hash
1491 || linecmp(clp
->line
, clp
->line
+ 1,
1492 (unsigned int) (__virtscr
->maxx
- 1))
1493 || cellcmp(clp
->line
, buf
)) {
1494 #endif /* HAVE_WCHAR */
1495 for (i
= __virtscr
->maxx
;
1498 (void) memcpy(clp
->line
+ i
-
1499 BLANKSIZE
, buf
, sizeof(buf
));
1501 (void) memcpy(clp
->line
, buf
, i
*
1504 __CTRACE(__CTRACE_REFRESH
,
1505 " blanked out: dirty\n");
1507 clp
->hash
= blank_hash
;
1508 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1511 __CTRACE(__CTRACE_REFRESH
,
1512 " -- blank line already: dirty\n");
1514 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1518 __CTRACE(__CTRACE_REFRESH
, " -- dirty\n");
1520 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1522 if (target
== cur_period
) {
1524 tmp1
= curscr
->alines
[i
];
1532 __CTRACE(__CTRACE_REFRESH
, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
1533 for (i
= 0; i
< curscr
->maxy
; i
++) {
1534 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1535 for (j
= 0; j
< curscr
->maxx
; j
++)
1536 __CTRACE(__CTRACE_REFRESH
, "%c",
1537 curscr
->alines
[i
]->line
[j
].ch
);
1538 __CTRACE(__CTRACE_REFRESH
, "\n");
1539 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1540 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1541 __CTRACE(__CTRACE_REFRESH
, "%c",
1542 __virtscr
->alines
[i
]->line
[j
].ch
);
1543 __CTRACE(__CTRACE_REFRESH
, "\n");
1547 scrolln(starts
, startw
, curs
, bot
, top
);
1552 * Scroll n lines, where n is starts - startw.
1554 static void /* ARGSUSED */
1555 scrolln(starts
, startw
, curs
, bot
, top
)
1556 int starts
, startw
, curs
, bot
, top
;
1562 n
= starts
- startw
;
1566 * The initial tests that set __noqch don't let us reach here unless
1567 * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
1568 * scrolling can only shift the entire scrolling region, not just a
1569 * part of it, which means that the quickch() routine is going to be
1570 * sadly disappointed in us if we don't have cs as well.
1572 * If cs, ho and SF/sf are set, can use the scrolling region. Because
1573 * the cursor position after cs is undefined, we need ho which gives us
1574 * the ability to move to somewhere without knowledge of the current
1575 * location of the cursor. Still call __mvcur() anyway, to update its
1576 * idea of where the cursor is.
1578 * When the scrolling region has been set, the cursor has to be at the
1579 * last line of the region to make the scroll happen.
1581 * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr
1582 * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not
1583 * SF/SR. So, if we're scrolling almost all of the screen, try and use
1584 * AL/DL, otherwise use the scrolling region. The "almost all" is a
1585 * shameless hack for vi.
1588 if (change_scroll_region
!= NULL
&& cursor_home
!= NULL
&&
1589 (parm_index
!= NULL
||
1590 ((parm_insert_line
== NULL
|| parm_delete_line
== NULL
||
1591 top
> 3 || bot
+ 3 < __virtscr
->maxy
) &&
1592 scroll_forward
!= NULL
)))
1594 tputs(tiparm(change_scroll_region
, top
, bot
),
1596 __mvcur(oy
, ox
, 0, 0, 1);
1597 tputs(cursor_home
, 0, __cputchar
);
1598 __mvcur(0, 0, bot
, 0, 1);
1599 if (parm_index
!= NULL
)
1600 tputs(tiparm(parm_index
, n
),
1603 for (i
= 0; i
< n
; i
++)
1604 tputs(scroll_forward
, 0, __cputchar
);
1605 tputs(tiparm(change_scroll_region
,
1606 0, (int) __virtscr
->maxy
- 1), 0, __cputchar
);
1607 __mvcur(bot
, 0, 0, 0, 1);
1608 tputs(cursor_home
, 0, __cputchar
);
1609 __mvcur(0, 0, oy
, ox
, 1);
1613 /* Scroll up the block. */
1614 if (parm_index
!= NULL
&& top
== 0) {
1615 __mvcur(oy
, ox
, bot
, 0, 1);
1616 tputs(tiparm(parm_index
, n
), 0, __cputchar
);
1618 if (parm_delete_line
!= NULL
) {
1619 __mvcur(oy
, ox
, top
, 0, 1);
1620 tputs(tiparm(parm_delete_line
, n
),
1623 if (delete_line
!= NULL
) {
1624 __mvcur(oy
, ox
, top
, 0, 1);
1625 for (i
= 0; i
< n
; i
++)
1629 if (scroll_forward
!= NULL
&& top
== 0) {
1630 __mvcur(oy
, ox
, bot
, 0, 1);
1631 for (i
= 0; i
< n
; i
++)
1632 tputs(scroll_forward
, 0,
1637 /* Push down the bottom region. */
1638 __mvcur(top
, 0, bot
- n
+ 1, 0, 1);
1639 if (parm_insert_line
!= NULL
)
1640 tputs(tiparm(parm_insert_line
, n
), 0, __cputchar
);
1642 if (insert_line
!= NULL
)
1643 for (i
= 0; i
< n
; i
++)
1644 tputs(insert_line
, 0, __cputchar
);
1647 __mvcur(bot
- n
+ 1, 0, oy
, ox
, 1);
1653 * If cs, ho and SR/sr are set, can use the scrolling region.
1654 * See the above comments for details.
1656 if (change_scroll_region
!= NULL
&& cursor_home
!= NULL
&&
1657 (parm_rindex
!= NULL
||
1658 ((parm_insert_line
== NULL
|| parm_delete_line
== NULL
||
1660 bot
+ 3 < __virtscr
->maxy
) && scroll_reverse
!= NULL
)))
1662 tputs(tiparm(change_scroll_region
, top
, bot
),
1664 __mvcur(oy
, ox
, 0, 0, 1);
1665 tputs(cursor_home
, 0, __cputchar
);
1666 __mvcur(0, 0, top
, 0, 1);
1668 if (parm_rindex
!= NULL
)
1669 tputs(tiparm(parm_rindex
, -n
),
1672 for (i
= n
; i
< 0; i
++)
1673 tputs(scroll_reverse
, 0, __cputchar
);
1674 tputs(tiparm(change_scroll_region
,
1675 0, (int) __virtscr
->maxy
- 1), 0, __cputchar
);
1676 __mvcur(top
, 0, 0, 0, 1);
1677 tputs(cursor_home
, 0, __cputchar
);
1678 __mvcur(0, 0, oy
, ox
, 1);
1682 /* Preserve the bottom lines. */
1683 __mvcur(oy
, ox
, bot
+ n
+ 1, 0, 1);
1684 if (parm_rindex
!= NULL
&& bot
== __virtscr
->maxy
)
1685 tputs(tiparm(parm_rindex
, -n
), 0, __cputchar
);
1687 if (parm_delete_line
!= NULL
)
1688 tputs(tiparm(parm_delete_line
, -n
),
1691 if (delete_line
!= NULL
)
1692 for (i
= n
; i
< 0; i
++)
1696 if (scroll_reverse
!= NULL
&&
1697 bot
== __virtscr
->maxy
)
1698 for (i
= n
; i
< 0; i
++)
1699 tputs(scroll_reverse
, 0,
1704 /* Scroll the block down. */
1705 __mvcur(bot
+ n
+ 1, 0, top
, 0, 1);
1706 if (parm_insert_line
!= NULL
)
1707 tputs(tiparm(parm_insert_line
, -n
), 0, __cputchar
);
1709 if (insert_line
!= NULL
)
1710 for (i
= n
; i
< 0; i
++)
1711 tputs(insert_line
, 0, __cputchar
);
1714 __mvcur(top
, 0, oy
, ox
, 1);
1720 * Unset attributes on curscr. Leave standout, attribute and colour
1721 * modes if necessary (!ms). Always leave altcharset (xterm at least
1722 * ignores a cursor move if we don't).
1725 __unsetattr(int checkms
)
1730 if (!move_standout_mode
) {
1738 __CTRACE(__CTRACE_REFRESH
,
1739 "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n",
1740 checkms
, move_standout_mode
? "TRUE" : "FALSE", curscr
->wattr
);
1744 * Don't leave the screen in standout mode (check against ms). Check
1745 * to see if we also turn off underscore, attributes and colour.
1747 if (curscr
->wattr
& __STANDOUT
&& isms
) {
1748 tputs(exit_standout_mode
, 0, __cputchar
);
1749 curscr
->wattr
&= __mask_se
;
1752 * Don't leave the screen in underscore mode (check against ms).
1753 * Check to see if we also turn off attributes. Assume that we
1754 * also turn off colour.
1756 if (curscr
->wattr
& __UNDERSCORE
&& isms
) {
1757 tputs(exit_underline_mode
, 0, __cputchar
);
1758 curscr
->wattr
&= __mask_ue
;
1761 * Don't leave the screen with attributes set (check against ms).
1762 * Assume that also turn off colour.
1764 if (curscr
->wattr
& __TERMATTR
&& isms
) {
1765 tputs(exit_attribute_mode
, 0, __cputchar
);
1766 curscr
->wattr
&= __mask_me
;
1768 /* Don't leave the screen with altcharset set (don't check ms). */
1769 if (curscr
->wattr
& __ALTCHARSET
) {
1770 tputs(exit_alt_charset_mode
, 0, __cputchar
);
1771 curscr
->wattr
&= ~__ALTCHARSET
;
1773 /* Don't leave the screen with colour set (check against ms). */
1774 if (__using_color
&& isms
)
1775 __unset_color(curscr
);
1779 /* compare two cells on screen, must have the same forground/background,
1780 * and the same sequence of non-spacing characters */
1782 cellcmp( __LDATA
*x
, __LDATA
*y
)
1784 nschar_t
*xnp
= x
->nsp
, *ynp
= y
->nsp
;
1785 int ret
= ( x
->ch
== y
->ch
) & ( x
->attr
== y
->attr
);
1791 if (( xnp
&& !ynp
) || ( !xnp
&& ynp
))
1794 while ( xnp
&& ynp
) {
1795 if ( xnp
->ch
!= ynp
->ch
)
1800 return ( !xnp
&& !ynp
);
1803 /* compare two line segments */
1805 linecmp( __LDATA
*xl
, __LDATA
*yl
, size_t len
)
1808 __LDATA
*xp
= xl
, *yp
= yl
;
1810 for ( i
= 0; i
< len
; i
++, xp
++, yp
++ ) {
1811 if ( !cellcmp( xp
, yp
))
1818 * Output the non-spacing characters associated with the given character
1819 * cell to the screen.
1823 __cursesi_putnsp(nschar_t
*nsp
, const int wy
, const int wx
)
1827 /* this shuts up gcc warnings about wx and wy not being used */
1833 __cputwchar((int) p
->ch
);
1835 __CTRACE(__CTRACE_REFRESH
,
1836 "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n",
1843 #endif /* HAVE_WCHAR */