1 /* $NetBSD: refresh.c,v 1.79 2014/02/20 09:42:42 blymn 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.79 2014/02/20 09:42:42 blymn 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
, dy_off
, dx_off
, endy
;
148 __LINE
*wlp
, *vlp
, *dwlp
;
149 WINDOW
*sub_win
, *orig
, *swin
, *dwin
;
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 if (win
->flags
& __ISDERWIN
)
167 * Recurse through any sub-windows, mark as dirty lines on the parent
168 * window that are dirty on the sub-window and clear the dirty flag on
171 if (dwin
->orig
== 0) {
173 for (sub_win
= dwin
->nextp
; sub_win
!= orig
;
174 sub_win
= sub_win
->nextp
) {
175 if (sub_win
->flags
& __ISDERWIN
)
178 __CTRACE(__CTRACE_REFRESH
,
179 "wnout_refresh: win %p, sub_win %p\n",
182 for (sy
= 0; sy
< sub_win
->maxy
; sy
++) {
183 if (sub_win
->alines
[sy
]->flags
& __ISDIRTY
) {
184 orig
->alines
[sy
+ sub_win
->begy
- orig
->begy
]->flags
186 sub_win
->alines
[sy
]->flags
189 if (sub_win
->alines
[sy
]->flags
& __ISFORCED
) {
190 orig
->alines
[sy
+ sub_win
->begy
- orig
->begy
]->flags
192 sub_win
->alines
[sy
]->flags
199 /* Check that cursor position on "win" is valid for "__virtscr" */
200 if (dwin
->cury
+ wbegy
- begy
< screen
->__virtscr
->maxy
&&
201 dwin
->cury
+ wbegy
- begy
>= 0 && dwin
->cury
< maxy
- begy
)
202 screen
->__virtscr
->cury
= dwin
->cury
+ wbegy
- begy
;
203 if (dwin
->curx
+ wbegx
- begx
< screen
->__virtscr
->maxx
&&
204 dwin
->curx
+ wbegx
- begx
>= 0 && dwin
->curx
< maxx
- begx
)
205 screen
->__virtscr
->curx
= dwin
->curx
+ wbegx
- begx
;
207 /* Copy the window flags from "win" to "__virtscr" */
208 if (dwin
->flags
& __CLEAROK
) {
209 if (dwin
->flags
& __FULLWIN
)
210 screen
->__virtscr
->flags
|= __CLEAROK
;
211 dwin
->flags
&= ~__CLEAROK
;
213 screen
->__virtscr
->flags
&= ~__LEAVEOK
;
214 screen
->__virtscr
->flags
|= dwin
->flags
;
216 if ((dwin
->flags
& __ISDERWIN
) != 0)
221 for (wy
= begy
, y_off
= wbegy
, dy_off
= 0; wy
< endy
&&
222 y_off
< screen
->__virtscr
->maxy
; wy
++, y_off
++, dy_off
++) {
223 wlp
= swin
->alines
[wy
];
224 dwlp
= dwin
->alines
[dy_off
];
226 __CTRACE(__CTRACE_REFRESH
,
227 "_wnoutrefresh: wy %d\tf %d\tl %d\tflags %x\n",
228 wy
, *wlp
->firstchp
, *wlp
->lastchp
, wlp
->flags
);
230 if ((dwin
->flags
& __ISDERWIN
) != 0) {
231 __CTRACE(__CTRACE_REFRESH
,
232 "_wnoutrefresh: derwin wy %d\tf %d\tl %d\tflags %x\n",
233 dy_off
, *dwlp
->firstchp
, *dwlp
->lastchp
, dwlp
->flags
);
234 __CTRACE(__CTRACE_REFRESH
,
235 "_wnoutrefresh: derwin maxx %d\tch_off %d\n",
236 dwin
->maxx
, dwin
->ch_off
);
239 if (((wlp
->flags
& (__ISDIRTY
| __ISFORCED
)) == 0) &&
240 ((dwlp
->flags
& (__ISDIRTY
| __ISFORCED
)) == 0))
242 vlp
= screen
->__virtscr
->alines
[y_off
];
244 if ((*wlp
->firstchp
< maxx
+ swin
->ch_off
&&
245 *wlp
->lastchp
>= swin
->ch_off
) ||
246 ((((dwin
->flags
& __ISDERWIN
) != 0) &&
247 (*dwlp
->firstchp
< dwin
->maxx
+ dwin
->ch_off
&&
248 *dwlp
->lastchp
>= dwin
->ch_off
)))) {
249 /* Set start column */
254 * if a derwin then source change pointers aren't
257 if ((dwin
->flags
& __ISDERWIN
) != 0)
260 if (*wlp
->firstchp
- swin
->ch_off
> 0) {
261 wx
+= *wlp
->firstchp
- swin
->ch_off
;
262 x_off
+= *wlp
->firstchp
- swin
->ch_off
;
265 if (mx
> *wlp
->lastchp
- swin
->ch_off
+ 1)
266 mx
= *dwlp
->lastchp
- dwin
->ch_off
+ 1;
267 if (x_off
+ (mx
- wx
) > __virtscr
->maxx
)
268 mx
-= (x_off
+ maxx
) - __virtscr
->maxx
;
271 /* Copy line from "win" to "__virtscr". */
274 __CTRACE(__CTRACE_REFRESH
,
275 "_wnoutrefresh: copy from %d, "
276 "%d to %d, %d: %s, 0x%x",
277 wy
, wx
, y_off
, x_off
,
278 unctrl(wlp
->line
[wx
].ch
),
282 vlp
->line
[x_off
].ch
= wlp
->line
[wx
].ch
;
283 /* Copy attributes */
284 vlp
->line
[x_off
].attr
= wlp
->line
[wx
].attr
;
285 /* Check for nca conflict with colour */
286 if ((vlp
->line
[x_off
].attr
& __COLOR
) &&
287 (vlp
->line
[x_off
].attr
&
288 _cursesi_screen
->nca
))
289 vlp
->line
[x_off
].attr
&= ~__COLOR
;
290 if (win
->flags
& __ISDERWIN
) {
291 dwlp
->line
[dx_off
].ch
=
293 dwlp
->line
[dx_off
].attr
=
299 == (wchar_t)btowc((int) win
->bch
)) {
300 vlp
->line
[x_off
].ch
= win
->bch
;
301 SET_WCOL( vlp
->line
[x_off
], 1 );
302 if (_cursesi_copy_nsp(win
->bnsp
,
306 if (win
->flags
& __ISDERWIN
) {
307 dwlp
->line
[dx_off
].ch
=
309 SET_WCOL(dwlp
->line
[dx_off
], 1);
310 if (_cursesi_copy_nsp(win
->bnsp
,
316 #endif /* HAVE_WCHAR */
318 __CTRACE(__CTRACE_REFRESH
, " = %s, 0x%x\n",
319 unctrl(vlp
->line
[x_off
].ch
),
320 vlp
->line
[x_off
].attr
);
327 /* Set flags on "__virtscr" and unset on "win". */
328 if (wlp
->flags
& __ISPASTEOL
)
329 vlp
->flags
|= __ISPASTEOL
;
331 vlp
->flags
&= ~__ISPASTEOL
;
332 if (wlp
->flags
& __ISDIRTY
)
333 vlp
->flags
|= __ISDIRTY
;
334 if (wlp
->flags
& __ISFORCED
)
335 vlp
->flags
|= __ISFORCED
;
338 __CTRACE(__CTRACE_REFRESH
,
339 "win: firstch = %d, lastch = %d\n",
340 *wlp
->firstchp
, *wlp
->lastchp
);
341 if (win
->flags
& __ISDERWIN
) {
342 __CTRACE(__CTRACE_REFRESH
,
343 "derwin: fistch = %d, lastch = %d\n",
344 *dwlp
->firstchp
, *dwlp
->lastchp
);
347 /* Set change pointers on "__virtscr". */
349 *wlp
->firstchp
+ wbegx
- win
->ch_off
)
351 *wlp
->firstchp
+ wbegx
- win
->ch_off
;
353 *wlp
->lastchp
+ wbegx
- win
->ch_off
)
355 *wlp
->lastchp
+ wbegx
- win
->ch_off
;
357 if (win
->flags
& __ISDERWIN
) {
359 *dwlp
->firstchp
+ wbegx
- dwin
->ch_off
) {
361 *dwlp
->firstchp
+ wbegx
363 vlp
->flags
|= __ISDIRTY
;
367 *dwlp
->lastchp
+ wbegx
- dwin
->ch_off
) {
368 *vlp
->lastchp
= *dwlp
->lastchp
369 + wbegx
- dwin
->ch_off
;
370 vlp
->flags
|= __ISDIRTY
;
375 __CTRACE(__CTRACE_REFRESH
,
376 "__virtscr: firstch = %d, lastch = %d\n",
377 *vlp
->firstchp
, *vlp
->lastchp
);
380 * Unset change pointers only if a window and we
381 * are not forcing a redraw. A pad can be displayed
382 * again without any of the contents changing.
384 if ((!(win
->flags
& __ISPAD
)) ||
385 ((wlp
->flags
& __ISFORCED
) == __ISFORCED
)) {
386 /* Set change pointers on "win". */
387 if (*wlp
->firstchp
>= win
->ch_off
)
388 *wlp
->firstchp
= maxx
+ win
->ch_off
;
389 if (*wlp
->lastchp
< maxx
+ win
->ch_off
)
390 *wlp
->lastchp
= win
->ch_off
;
391 if ((*wlp
->lastchp
< *wlp
->firstchp
) ||
392 (*wlp
->firstchp
>= maxx
+ win
->ch_off
) ||
393 (*wlp
->lastchp
<= win
->ch_off
)) {
395 __CTRACE(__CTRACE_REFRESH
,
397 "line %d notdirty\n", wy
);
399 wlp
->flags
&= ~__ISDIRTY
;
409 * Make the current screen look like "win" over the area covered by
413 wrefresh(WINDOW
*win
)
419 __CTRACE(__CTRACE_REFRESH
, "wrefresh: win %p\n", win
);
422 _cursesi_screen
->curwin
= (win
== _cursesi_screen
->curscr
);
423 if (!_cursesi_screen
->curwin
) {
425 if ((win
->flags
& __ISDERWIN
) == __ISDERWIN
) {
429 __CTRACE(__CTRACE_REFRESH
, "wrefresh: derwin, begy = %d, begx = %x\n",
433 retval
= _cursesi_wnoutrefresh(_cursesi_screen
, win
, pbegy
,
434 pbegx
, win
->begy
, win
->begx
, win
->maxy
, win
->maxx
);
439 if (!(win
->flags
& __LEAVEOK
)) {
440 win
->cury
= max(0, curscr
->cury
- win
->begy
);
441 win
->curx
= max(0, curscr
->curx
- win
->begx
);
444 _cursesi_screen
->curwin
= 0;
450 * Make the current screen look like "pad" over the area coverd by
451 * the specified area of pad.
454 prefresh(WINDOW
*pad
, int pbegy
, int pbegx
, int sbegy
, int sbegx
,
455 int smaxy
, int smaxx
)
460 __CTRACE(__CTRACE_REFRESH
, "prefresh: pad %p, flags 0x%08x\n",
463 /* Retain values in case pechochar() is called. */
471 /* Use pnoutrefresh() to avoid duplicating code here */
472 retval
= pnoutrefresh(pad
, pbegy
, pbegx
, sbegy
, sbegx
, smaxy
, smaxx
);
475 if (!(pad
->flags
& __LEAVEOK
)) {
476 pad
->cury
= max(0, curscr
->cury
- pad
->begy
);
477 pad
->curx
= max(0, curscr
->curx
- pad
->begx
);
485 * Make the current screen look like the virtual window "__virtscr".
493 int dnum
, was_cleared
;
498 #endif /* HAVE_WCHAR */
500 /* Check if we need to restart ... */
501 if (_cursesi_screen
->endwin
)
504 if (_cursesi_screen
->curwin
)
507 win
= _cursesi_screen
->__virtscr
;
509 /* Initialize loop parameters. */
510 _cursesi_screen
->ly
= curscr
->cury
;
511 _cursesi_screen
->lx
= curscr
->curx
;
514 if (!_cursesi_screen
->curwin
) {
515 for (wy
= 0; wy
< win
->maxy
; wy
++) {
516 wlp
= win
->alines
[wy
];
517 if (wlp
->flags
& __ISDIRTY
) {
519 wlp
->hash
= __hash(wlp
->line
,
520 (size_t)(win
->maxx
* __LDATASIZE
));
523 for ( x
= 0; x
< win
->maxx
; x
++ ) {
524 lp
= &wlp
->line
[ x
];
525 wlp
->hash
= __hash_more( &lp
->ch
,
526 sizeof( wchar_t ), wlp
->hash
);
527 wlp
->hash
= __hash_more( &lp
->attr
,
528 sizeof( attr_t
), wlp
->hash
);
541 #endif /* HAVE_WCHAR */
547 if ((win
->flags
& __CLEAROK
) || (curscr
->flags
& __CLEAROK
) ||
548 _cursesi_screen
->curwin
) {
549 if (curscr
->wattr
& __COLOR
)
551 tputs(clear_screen
, 0, __cputchar
);
552 _cursesi_screen
->ly
= 0;
553 _cursesi_screen
->lx
= 0;
554 if (!_cursesi_screen
->curwin
) {
555 curscr
->flags
&= ~__CLEAROK
;
561 win
->flags
&= ~__CLEAROK
;
562 /* note we cleared for later */
565 if (!cursor_address
) {
568 if (!_cursesi_screen
->curwin
)
572 __CTRACE(__CTRACE_REFRESH
, "doupdate: (%p): curwin = %d\n", win
,
573 _cursesi_screen
->curwin
);
574 __CTRACE(__CTRACE_REFRESH
, "doupdate: \tfirstch\tlastch\n");
577 if (!_cursesi_screen
->curwin
) {
579 * Invoke quickch() only if more than a quarter of the lines
580 * in the window are dirty.
582 for (wy
= 0, dnum
= 0; wy
< win
->maxy
; wy
++)
583 if (win
->alines
[wy
]->flags
& __ISDIRTY
)
585 if (!__noqch
&& dnum
> (int) win
->maxy
/ 4)
593 __CTRACE(__CTRACE_REFRESH
,
594 "#####################################\n");
595 __CTRACE(__CTRACE_REFRESH
,
596 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
597 stdscr
, curscr
, _cursesi_screen
->__virtscr
);
598 for (i
= 0; i
< curscr
->maxy
; i
++) {
599 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
600 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
601 curscr
->alines
[i
]->hash
);
602 for (j
= 0; j
< curscr
->maxx
; j
++)
603 __CTRACE(__CTRACE_REFRESH
, "%c",
604 curscr
->alines
[i
]->line
[j
].ch
);
605 __CTRACE(__CTRACE_REFRESH
, "\n");
606 __CTRACE(__CTRACE_REFRESH
, " attr:");
607 for (j
= 0; j
< curscr
->maxx
; j
++)
608 __CTRACE(__CTRACE_REFRESH
, " %x",
609 curscr
->alines
[i
]->line
[j
].attr
);
610 __CTRACE(__CTRACE_REFRESH
, "\n");
611 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
612 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
613 win
->alines
[i
]->hash
);
614 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
615 win
->alines
[i
]->flags
);
616 for (j
= 0; j
< win
->maxx
; j
++)
617 __CTRACE(__CTRACE_REFRESH
, "%c",
618 win
->alines
[i
]->line
[j
].ch
);
619 __CTRACE(__CTRACE_REFRESH
, "\n");
620 __CTRACE(__CTRACE_REFRESH
, " attr:");
621 for (j
= 0; j
< win
->maxx
; j
++)
622 __CTRACE(__CTRACE_REFRESH
, " %x",
623 win
->alines
[i
]->line
[j
].attr
);
624 __CTRACE(__CTRACE_REFRESH
, "\n");
626 __CTRACE(__CTRACE_REFRESH
, " nsp:");
627 for (j
= 0; j
< curscr
->maxx
; j
++)
628 __CTRACE(__CTRACE_REFRESH
, " %p",
629 win
->alines
[i
]->line
[j
].nsp
);
630 __CTRACE(__CTRACE_REFRESH
, "\n");
631 __CTRACE(__CTRACE_REFRESH
, " bnsp:");
632 for (j
= 0; j
< curscr
->maxx
; j
++)
633 __CTRACE(__CTRACE_REFRESH
, " %p",
635 __CTRACE(__CTRACE_REFRESH
, "\n");
636 #endif /* HAVE_WCHAR */
641 for (wy
= 0; wy
< win
->maxy
; wy
++) {
642 wlp
= win
->alines
[wy
];
643 vlp
= _cursesi_screen
->__virtscr
->alines
[win
->begy
+ wy
];
644 /* XXX: remove this debug */
646 __CTRACE(__CTRACE_REFRESH
,
647 "doupdate: wy %d\tf: %d\tl:%d\tflags %x\n",
648 wy
, *wlp
->firstchp
, *wlp
->lastchp
, wlp
->flags
);
650 if (!_cursesi_screen
->curwin
)
651 curscr
->alines
[wy
]->hash
= wlp
->hash
;
652 if ((wlp
->flags
& __ISDIRTY
) ||
653 (wlp
->flags
& __ISFORCED
)) {
655 __CTRACE(__CTRACE_REFRESH
,
656 "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy
,
657 *wlp
->firstchp
, *wlp
->lastchp
);
660 * We have just cleared so don't force an update
661 * otherwise we spray neeedless blanks to a cleared
664 if (was_cleared
== 1)
665 win
->alines
[wy
]->flags
&= ~__ISFORCED
;
667 if (makech(wy
) == ERR
)
670 if (*wlp
->firstchp
>= 0)
671 *wlp
->firstchp
= win
->maxx
;
672 if (*wlp
->lastchp
< win
->maxx
)
673 *wlp
->lastchp
= win
->ch_off
;
674 if (*wlp
->lastchp
< *wlp
->firstchp
) {
676 __CTRACE(__CTRACE_REFRESH
,
677 "doupdate: line %d notdirty\n", wy
);
679 wlp
->flags
&= ~(__ISDIRTY
| __ISFORCED
);
685 * virtscr is now synced for the line, unset the change
688 if (*vlp
->firstchp
>= 0)
689 *vlp
->firstchp
= _cursesi_screen
->__virtscr
->maxx
;
690 if (*vlp
->lastchp
<= _cursesi_screen
->__virtscr
->maxx
)
694 __CTRACE(__CTRACE_REFRESH
, "\t%d\t%d\n",
695 *wlp
->firstchp
, *wlp
->lastchp
);
700 __CTRACE(__CTRACE_REFRESH
, "doupdate: ly=%d, lx=%d\n",
701 _cursesi_screen
->ly
, _cursesi_screen
->lx
);
704 if (_cursesi_screen
->curwin
)
705 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
706 win
->cury
, win
->curx
);
708 if (win
->flags
& __LEAVEOK
) {
709 curscr
->cury
= _cursesi_screen
->ly
;
710 curscr
->curx
= _cursesi_screen
->lx
;
712 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
713 win
->cury
, win
->curx
);
714 curscr
->cury
= win
->cury
;
715 curscr
->curx
= win
->curx
;
719 /* Don't leave the screen with attributes set. */
726 __CTRACE(__CTRACE_REFRESH
,
727 "***********after*****************\n");
728 __CTRACE(__CTRACE_REFRESH
,
729 "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
730 stdscr
, curscr
, _cursesi_screen
->__virtscr
);
731 for (i
= 0; i
< curscr
->maxy
; i
++) {
732 for (j
= 0; j
< curscr
->maxx
; j
++)
733 __CTRACE(__CTRACE_REFRESH
,
734 "[%d,%d](%x,%x,%p)-(%x,%x,%p)\n",
736 curscr
->alines
[i
]->line
[j
].ch
,
737 curscr
->alines
[i
]->line
[j
].attr
,
738 curscr
->alines
[i
]->line
[j
].nsp
,
739 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].ch
,
740 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].attr
,
741 _cursesi_screen
->__virtscr
->alines
[i
]->line
[j
].nsp
);
744 #endif /* HAVE_WCHAR */
746 return fflush(_cursesi_screen
->outfd
) == EOF
? ERR
: OK
;
751 * Make a change on the screen.
757 static __LDATA blank
;
758 __LDATA
*nsp
, *csp
, *cp
, *cep
;
760 size_t clsp
, nlsp
; /* Last space in lines. */
763 attr_t lspc
; /* Last space colour */
767 nlsp
= lspc
= 0; /* XXX gcc -Wuninitialized */
769 if (_cursesi_screen
->curwin
)
774 blank
.ch
= ( wchar_t )btowc(( int ) win
->bch
);
776 if (_cursesi_copy_nsp(win
->bnsp
, &blank
) == ERR
)
778 SET_WCOL( blank
, 1 );
779 #endif /* HAVE_WCHAR */
786 __CTRACE(__CTRACE_REFRESH
,
787 "[makech-before]wy=%d,curscr(%p)-__virtscr(%p)\n",
788 wy
, curscr
, __virtscr
);
789 for (x
= 0; x
< curscr
->maxx
; x
++) {
790 lp
= &curscr
->alines
[wy
]->line
[x
];
791 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
792 __CTRACE(__CTRACE_REFRESH
,
793 "[%d,%d](%x,%x,%x,%x,%p)-"
794 "(%x,%x,%x,%x,%p)\n",
795 wy
, x
, lp
->ch
, lp
->attr
,
796 win
->bch
, win
->battr
, lp
->nsp
,
798 win
->bch
, win
->battr
, vlp
->nsp
);
801 #endif /* HAVE_WCHAR */
803 /* Is the cursor still on the end of the last line? */
804 if (wy
> 0 && curscr
->alines
[wy
- 1]->flags
& __ISPASTEOL
) {
805 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
,
806 _cursesi_screen
->ly
+ 1, 0);
807 _cursesi_screen
->ly
++;
808 _cursesi_screen
->lx
= 0;
810 wlp
= win
->alines
[wy
];
811 wx
= *win
->alines
[wy
]->firstchp
;
817 lch
= *win
->alines
[wy
]->lastchp
;
821 if (lch
>= (int) win
->maxx
)
824 if (_cursesi_screen
->curwin
) {
827 __CTRACE(__CTRACE_REFRESH
, "makech: csp is blank\n");
830 csp
= &curscr
->alines
[wy
]->line
[wx
];
832 __CTRACE(__CTRACE_REFRESH
,
833 "makech: csp is on curscr:(%d,%d)\n", wy
, wx
);
837 nsp
= &win
->alines
[wy
]->line
[wx
];
839 if ( _cursesi_screen
->curwin
)
840 __CTRACE(__CTRACE_REFRESH
,
841 "makech: nsp is at curscr:(%d,%d)\n", wy
, wx
);
843 __CTRACE(__CTRACE_REFRESH
,
844 "makech: nsp is at __virtscr:(%d,%d)\n", wy
, wx
);
846 if (clr_eol
&& !_cursesi_screen
->curwin
) {
847 cp
= &win
->alines
[wy
]->line
[win
->maxx
- 1];
848 lspc
= cp
->attr
& __COLOR
;
850 while (cp
->ch
== ' ' && cp
->attr
== lspc
) /* XXX */
851 if (cp
-- <= win
->alines
[wy
]->line
)
854 while (cp
->ch
== ( wchar_t )btowc(( int )' ' )
855 && ( cp
->attr
& WA_ATTRIBUTES
) == lspc
)
856 if (cp
-- <= win
->alines
[wy
]->line
)
858 #endif /* HAVE_WCHAR */
859 if (win
->alines
[wy
]->line
> cp
)
862 nlsp
= cp
- win
->alines
[wy
]->line
;
864 if (!_cursesi_screen
->curwin
)
871 __CTRACE(__CTRACE_REFRESH
, "makech: wx=%d,lch=%d\n", wx
, lch
);
874 if (!(wlp
->flags
& __ISFORCED
) &&
875 (memcmp(nsp
, csp
, sizeof(__LDATA
)) == 0)) {
878 memcmp(nsp
, csp
, sizeof(__LDATA
)) == 0) {
880 if (!_cursesi_screen
->curwin
)
890 __CTRACE(__CTRACE_REFRESH
, "makech: nsp=(%x,%x,%x,%x,%p)\n",
891 nsp
->ch
, nsp
->attr
, win
->bch
, win
->battr
, nsp
->nsp
);
892 __CTRACE(__CTRACE_REFRESH
, "makech: csp=(%x,%x,%x,%x,%p)\n",
893 csp
->ch
, csp
->attr
, win
->bch
, win
->battr
, csp
->nsp
);
895 if (!(wlp
->flags
& __ISFORCED
) &&
896 (((nsp
->attr
& __WCWIDTH
) != __WCWIDTH
) &&
897 cellcmp(nsp
, csp
))) {
899 while (wx
<= lch
&& cellcmp( csp
, nsp
)) {
901 if (!_cursesi_screen
->curwin
)
909 #endif /* HAVE_WCHAR */
910 domvcur(_cursesi_screen
->ly
, _cursesi_screen
->lx
, wy
, wx
);
913 __CTRACE(__CTRACE_REFRESH
, "makech: 1: wx = %d, ly= %d, "
914 "lx = %d, newy = %d, newx = %d\n",
915 wx
, _cursesi_screen
->ly
, _cursesi_screen
->lx
, wy
, wx
);
917 _cursesi_screen
->ly
= wy
;
918 _cursesi_screen
->lx
= wx
;
920 while (wx
<= lch
&& (memcmp(nsp
, csp
, sizeof(__LDATA
)) != 0) ||
921 (wlp
->flags
& __ISFORCED
)) {
923 wx
>= nlsp
&& nsp
->ch
== ' ' && nsp
->attr
== lspc
) {
925 while ((!cellcmp(nsp
, csp
) || (wlp
->flags
& __ISFORCED
)) &&
927 if (ce
!= NULL
&& wx
>= nlsp
928 && nsp
->ch
== (wchar_t)btowc((int)' ') /* XXX */
929 && (nsp
->attr
& WA_ATTRIBUTES
) == lspc
) {
932 /* Check for clear to end-of-line. */
933 cep
= &curscr
->alines
[wy
]->line
[win
->maxx
- 1];
935 while (cep
->ch
== ' ' && cep
->attr
== lspc
) /* XXX */
937 while (cep
->ch
== (wchar_t)btowc((int)' ')
938 && (cep
->attr
& WA_ATTRIBUTES
) == lspc
)
939 #endif /* HAVE_WCHAR */
942 if (cep
> (curscr
->alines
[wy
]->line
+ win
->begx
* __LDATASIZE
))
943 clsp
= cep
- curscr
->alines
[wy
]->line
-
944 win
->begx
* __LDATASIZE
;
948 __CTRACE(__CTRACE_REFRESH
,
949 "makech: clsp = %zu, nlsp = %zu\n",
951 __CTRACE(__CTRACE_REFRESH
,
952 "makech: line = %p, cep = %p, begx = %u\n",
953 curscr
->alines
[wy
]->line
, cep
, win
->begx
);
955 if (((clsp
- nlsp
>= strlen(clr_eol
) &&
956 clsp
< win
->maxx
* __LDATASIZE
) ||
957 wy
== win
->maxy
- 1) &&
958 (!(lspc
& __COLOR
) ||
959 ((lspc
& __COLOR
) && back_color_erase
))) {
963 (curscr
->wattr
& __COLOR
)))
964 __set_color(curscr
, lspc
&
966 tputs(clr_eol
, 0, __cputchar
);
967 _cursesi_screen
->lx
= wx
+ win
->begx
;
968 while (wx
++ <= clsp
) {
971 csp
->ch
= ' '; /* XXX */
973 csp
->ch
= (wchar_t)btowc((int)' ');
975 #endif /* HAVE_WCHAR */
984 __CTRACE(__CTRACE_REFRESH
,
985 "makech: have attr %08x, need attr %08x\n",
1001 off
= (~nsp
->attr
& curscr
->wattr
)
1010 * Unset attributes as appropriate. Unset first
1011 * so that the relevant attributes can be reset
1012 * (because 'me' unsets 'mb', 'md', 'mh', 'mk',
1013 * 'mp' and 'mr'). Check to see if we also turn off
1014 * standout, attributes and colour.
1016 if (off
& __TERMATTR
&& exit_attribute_mode
!= NULL
) {
1017 tputs(exit_attribute_mode
, 0, __cputchar
);
1018 curscr
->wattr
&= __mask_me
;
1023 * Exit underscore mode if appropriate.
1024 * Check to see if we also turn off standout,
1025 * attributes and colour.
1027 if (off
& __UNDERSCORE
&& exit_underline_mode
!= NULL
) {
1028 tputs(exit_underline_mode
, 0, __cputchar
);
1029 curscr
->wattr
&= __mask_ue
;
1034 * Exit standout mode as appropriate.
1035 * Check to see if we also turn off underscore,
1036 * attributes and colour.
1038 * Should use uc if so/se not available.
1040 if (off
& __STANDOUT
&& exit_standout_mode
!= NULL
) {
1041 tputs(exit_standout_mode
, 0, __cputchar
);
1042 curscr
->wattr
&= __mask_se
;
1046 if (off
& __ALTCHARSET
&& exit_alt_charset_mode
!= NULL
) {
1047 tputs(exit_alt_charset_mode
, 0, __cputchar
);
1048 curscr
->wattr
&= ~__ALTCHARSET
;
1051 /* Set/change colour as appropriate. */
1053 __set_color(curscr
, nsp
->attr
& __COLOR
);
1055 on
= (nsp
->attr
& ~curscr
->wattr
)
1064 * Enter standout mode if appropriate.
1066 if (on
& __STANDOUT
&&
1067 enter_standout_mode
!= NULL
&&
1068 exit_standout_mode
!= NULL
)
1070 tputs(enter_standout_mode
, 0, __cputchar
);
1071 curscr
->wattr
|= __STANDOUT
;
1075 * Enter underscore mode if appropriate.
1077 * Should use uc if us/ue not available.
1079 if (on
& __UNDERSCORE
&&
1080 enter_underline_mode
!= NULL
&&
1081 exit_underline_mode
!= NULL
)
1083 tputs(enter_underline_mode
, 0, __cputchar
);
1084 curscr
->wattr
|= __UNDERSCORE
;
1088 * Set other attributes as appropriate.
1090 if (exit_attribute_mode
!= NULL
) {
1092 enter_blink_mode
!= NULL
)
1094 tputs(enter_blink_mode
, 0, __cputchar
);
1095 curscr
->wattr
|= __BLINK
;
1098 enter_bold_mode
!= NULL
)
1100 tputs(enter_bold_mode
, 0, __cputchar
);
1101 curscr
->wattr
|= __BOLD
;
1104 enter_dim_mode
!= NULL
)
1106 tputs(enter_dim_mode
, 0, __cputchar
);
1107 curscr
->wattr
|= __DIM
;
1110 enter_secure_mode
!= NULL
)
1112 tputs(enter_secure_mode
, 0, __cputchar
);
1113 curscr
->wattr
|= __BLANK
;
1115 if (on
& __PROTECT
&&
1116 enter_protected_mode
!= NULL
)
1118 tputs(enter_protected_mode
, 0, __cputchar
);
1119 curscr
->wattr
|= __PROTECT
;
1121 if (on
& __REVERSE
&&
1122 enter_reverse_mode
!= NULL
)
1124 tputs(enter_reverse_mode
, 0, __cputchar
);
1125 curscr
->wattr
|= __REVERSE
;
1129 enter_top_hl_mode
!= NULL
)
1131 tputs(enter_top_hl_mode
, 0, __cputchar
);
1132 curscr
->wattr
|= WA_TOP
;
1135 enter_low_hl_mode
!= NULL
)
1137 tputs(enter_low_hl_mode
, 0, __cputchar
);
1138 curscr
->wattr
|= WA_LOW
;
1141 enter_left_hl_mode
!= NULL
)
1143 tputs(enter_left_hl_mode
, 0, __cputchar
);
1144 curscr
->wattr
|= WA_LEFT
;
1146 if (on
& WA_RIGHT
&&
1147 enter_right_hl_mode
!= NULL
)
1149 tputs(enter_right_hl_mode
, 0, __cputchar
);
1150 curscr
->wattr
|= WA_RIGHT
;
1152 if (on
& WA_HORIZONTAL
&&
1153 enter_horizontal_hl_mode
!= NULL
)
1155 tputs(enter_horizontal_hl_mode
, 0, __cputchar
);
1156 curscr
->wattr
|= WA_HORIZONTAL
;
1158 if (on
& WA_VERTICAL
&&
1159 enter_vertical_hl_mode
!= NULL
)
1161 tputs(enter_vertical_hl_mode
, 0, __cputchar
);
1162 curscr
->wattr
|= WA_VERTICAL
;
1164 #endif /* HAVE_WCHAR */
1167 /* Enter/exit altcharset mode as appropriate. */
1168 if (on
& __ALTCHARSET
&& enter_alt_charset_mode
!= NULL
&&
1169 exit_alt_charset_mode
!= NULL
) {
1170 tputs(enter_alt_charset_mode
, 0, __cputchar
);
1171 curscr
->wattr
|= __ALTCHARSET
;
1175 if (wx
>= win
->maxx
&&
1176 wy
== win
->maxy
- 1 && !_cursesi_screen
->curwin
) {
1177 if (win
->flags
& __SCROLLOK
) {
1178 if (win
->flags
& __ENDLINE
)
1180 if (!(win
->flags
& __SCROLLWIN
)) {
1181 if (!_cursesi_screen
->curwin
) {
1182 csp
->attr
= nsp
->attr
;
1185 if (_cursesi_copy_nsp(nsp
->nsp
, csp
) == ERR
)
1187 #endif /* HAVE_WCHAR */
1190 __cputchar((int) nsp
->ch
);
1192 if ( WCOL( *nsp
) > 0 ) {
1193 __cputwchar((int)nsp
->ch
);
1195 __CTRACE(__CTRACE_REFRESH
,
1196 "makech: (%d,%d)putwchar(0x%x)\n",
1201 * Output non-spacing
1202 * characters for the
1205 __cursesi_putnsp(nsp
->nsp
,
1209 #endif /* HAVE_WCHAR */
1211 if (wx
< curscr
->maxx
) {
1212 domvcur(_cursesi_screen
->ly
, wx
,
1213 (int) (win
->maxy
- 1),
1214 (int) (win
->maxx
- 1));
1216 _cursesi_screen
->ly
= win
->maxy
- 1;
1217 _cursesi_screen
->lx
= win
->maxx
- 1;
1221 if (wx
< win
->maxx
|| wy
< win
->maxy
- 1 ||
1222 !(win
->flags
& __SCROLLWIN
)) {
1223 if (!_cursesi_screen
->curwin
) {
1224 csp
->attr
= nsp
->attr
;
1227 if (_cursesi_copy_nsp(nsp
->nsp
,
1230 #endif /* HAVE_WCHAR */
1234 __cputchar((int) nsp
->ch
);
1236 __CTRACE(__CTRACE_REFRESH
,
1237 "makech: putchar(%c)\n", nsp
->ch
& 0177);
1240 if (WCOL(*nsp
) > 0) {
1241 __cputwchar((int) nsp
->ch
);
1243 __CTRACE(__CTRACE_REFRESH
,
1244 "makech:(%d,%d) putwchar(%x)\n",
1245 wy
, wx
- 1, nsp
->ch
);
1246 __cursesi_putnsp(nsp
->nsp
, wy
, wx
);
1249 #endif /* HAVE_WCHAR */
1251 if (underline_char
&& ((nsp
->attr
& __STANDOUT
) ||
1252 (nsp
->attr
& __UNDERSCORE
))) {
1254 tputs(underline_char
, 0, __cputchar
);
1258 __CTRACE(__CTRACE_REFRESH
,
1259 "makech: 2: wx = %d, lx = %d\n",
1260 wx
, _cursesi_screen
->lx
);
1263 if (_cursesi_screen
->lx
== wx
) /* If no change. */
1265 _cursesi_screen
->lx
= wx
;
1266 if (_cursesi_screen
->lx
>= COLS
&& auto_right_margin
)
1267 _cursesi_screen
->lx
= COLS
- 1;
1269 if (wx
>= win
->maxx
) {
1270 domvcur(_cursesi_screen
->ly
,
1271 _cursesi_screen
->lx
,
1272 _cursesi_screen
->ly
,
1273 (int) (win
->maxx
- 1));
1274 _cursesi_screen
->lx
= win
->maxx
- 1;
1277 __CTRACE(__CTRACE_REFRESH
, "makech: 3: wx = %d, lx = %d\n",
1278 wx
, _cursesi_screen
->lx
);
1287 __CTRACE(__CTRACE_REFRESH
,
1288 "makech-after: curscr(%p)-__virtscr(%p)\n",
1289 curscr
, __virtscr
);
1290 for (x
= 0; x
< curscr
->maxx
; x
++) {
1291 lp
= &curscr
->alines
[wy
]->line
[x
];
1292 vlp
= &__virtscr
->alines
[wy
]->line
[x
];
1293 __CTRACE(__CTRACE_REFRESH
,
1294 "[%d,%d](%x,%x,%x,%x,%p)-"
1295 "(%x,%x,%x,%x,%p)\n",
1296 wy
, x
, lp
->ch
, lp
->attr
,
1297 win
->bch
, win
->battr
, lp
->nsp
,
1299 win
->bch
, win
->battr
, vlp
->nsp
);
1302 #endif /* HAVE_WCHAR */
1310 * Do a mvcur, leaving attributes if necessary.
1313 domvcur(oy
, ox
, ny
, nx
)
1317 __CTRACE(__CTRACE_REFRESH
, "domvcur: (%x,%d)=>(%d,%d)\n",
1321 if ( oy
== ny
&& ox
== nx
)
1323 __mvcur(oy
, ox
, ny
, nx
, 1);
1327 * Quickch() attempts to detect a pattern in the change of the window
1328 * in order to optimize the change, e.g., scroll n lines as opposed to
1329 * repainting the screen line by line.
1332 static __LDATA buf
[128];
1333 static u_int last_hash
;
1334 static size_t last_hash_len
;
1335 #define BLANKSIZE (sizeof(buf) / sizeof(buf[0]))
1340 #define THRESH (int) __virtscr->maxy / 4
1342 __LINE
*clp
, *tmp1
, *tmp2
;
1343 int bsize
, curs
, curw
, starts
, startw
, i
, j
;
1344 int n
, target
, cur_period
, bot
, top
, sc_region
;
1349 curs
= curw
= starts
= startw
= 0; /* XXX gcc -Wuninitialized */
1352 * Find how many lines from the top of the screen are unchanged.
1354 for (top
= 0; top
< __virtscr
->maxy
; top
++)
1356 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1357 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1358 memcmp(__virtscr
->alines
[top
]->line
,
1359 curscr
->alines
[top
]->line
,
1360 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1364 if (__virtscr
->alines
[top
]->flags
& __ISDIRTY
&&
1365 (__virtscr
->alines
[top
]->hash
!= curscr
->alines
[top
]->hash
||
1366 !linecmp(__virtscr
->alines
[top
]->line
,
1367 curscr
->alines
[top
]->line
,
1368 (size_t) __virtscr
->maxx
)))
1370 #endif /* HAVE_WCHAR */
1372 __virtscr
->alines
[top
]->flags
&= ~__ISDIRTY
;
1374 * Find how many lines from bottom of screen are unchanged.
1376 for (bot
= __virtscr
->maxy
- 1; bot
>= 0; bot
--)
1378 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1379 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1380 memcmp(__virtscr
->alines
[bot
]->line
,
1381 curscr
->alines
[bot
]->line
,
1382 (size_t) __virtscr
->maxx
* __LDATASIZE
)
1386 if (__virtscr
->alines
[bot
]->flags
& __ISDIRTY
&&
1387 (__virtscr
->alines
[bot
]->hash
!= curscr
->alines
[bot
]->hash
||
1388 !linecmp(__virtscr
->alines
[bot
]->line
,
1389 curscr
->alines
[bot
]->line
,
1390 (size_t) __virtscr
->maxx
)))
1392 #endif /* HAVE_WCHAR */
1394 __virtscr
->alines
[bot
]->flags
&= ~__ISDIRTY
;
1397 * Work round an xterm bug where inserting lines causes all the
1398 * inserted lines to be covered with the background colour we
1399 * set on the first line (even if we unset it for subsequent
1402 bcolor
= __virtscr
->alines
[min(top
,
1403 __virtscr
->maxy
- 1)]->line
[0].attr
& __COLOR
;
1404 for (i
= top
+ 1, j
= 0; i
< bot
; i
++) {
1405 if ((__virtscr
->alines
[i
]->line
[0].attr
& __COLOR
) != bcolor
) {
1406 bcolor
= __virtscr
->alines
[i
]->line
[__virtscr
->maxx
].
1416 * If we have a bottom unchanged region return. Scrolling the
1417 * bottom region up and then back down causes a screen jitter.
1418 * This will increase the number of characters sent to the screen
1419 * but it looks better.
1421 if (bot
< __virtscr
->maxy
- 1)
1423 #endif /* NO_JERKINESS */
1426 * Search for the largest block of text not changed.
1427 * Invariants of the loop:
1428 * - Startw is the index of the beginning of the examined block in
1430 * - Starts is the index of the beginning of the examined block in
1432 * - Curw is the index of one past the end of the exmined block in
1434 * - Curs is the index of one past the end of the exmined block in
1436 * - bsize is the current size of the examined block.
1439 for (bsize
= bot
- top
; bsize
>= THRESH
; bsize
--) {
1440 for (startw
= top
; startw
<= bot
- bsize
; startw
++)
1441 for (starts
= top
; starts
<= bot
- bsize
;
1443 for (curw
= startw
, curs
= starts
;
1444 curs
< starts
+ bsize
; curw
++, curs
++)
1445 if (__virtscr
->alines
[curw
]->hash
!=
1446 curscr
->alines
[curs
]->hash
)
1448 if (curs
!= starts
+ bsize
)
1450 for (curw
= startw
, curs
= starts
;
1451 curs
< starts
+ bsize
; curw
++, curs
++)
1453 if (memcmp(__virtscr
->alines
[curw
]->line
,
1454 curscr
->alines
[curs
]->line
,
1455 (size_t) __virtscr
->maxx
*
1459 if (!linecmp(__virtscr
->alines
[curw
]->line
,
1460 curscr
->alines
[curs
]->line
,
1461 (size_t) __virtscr
->maxx
))
1463 #endif /* HAVE_WCHAR */
1464 if (curs
== starts
+ bsize
)
1470 /* Did not find anything */
1475 __CTRACE(__CTRACE_REFRESH
, "quickch:bsize=%d, starts=%d, startw=%d, "
1476 "curw=%d, curs=%d, top=%d, bot=%d\n",
1477 bsize
, starts
, startw
, curw
, curs
, top
, bot
);
1481 * Make sure that there is no overlap between the bottom and top
1482 * regions and the middle scrolled block.
1489 n
= startw
- starts
;
1492 __CTRACE(__CTRACE_REFRESH
, "#####################################\n");
1493 for (i
= 0; i
< curscr
->maxy
; i
++) {
1494 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1495 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n", curscr
->alines
[i
]->hash
);
1496 for (j
= 0; j
< curscr
->maxx
; j
++)
1497 __CTRACE(__CTRACE_REFRESH
, "%c",
1498 curscr
->alines
[i
]->line
[j
].ch
);
1499 __CTRACE(__CTRACE_REFRESH
, "\n");
1500 __CTRACE(__CTRACE_REFRESH
, " attr:");
1501 for (j
= 0; j
< curscr
->maxx
; j
++)
1502 __CTRACE(__CTRACE_REFRESH
, " %x",
1503 curscr
->alines
[i
]->line
[j
].attr
);
1504 __CTRACE(__CTRACE_REFRESH
, "\n");
1505 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1506 __CTRACE(__CTRACE_REFRESH
, " 0x%x \n",
1507 __virtscr
->alines
[i
]->hash
);
1508 __CTRACE(__CTRACE_REFRESH
, " 0x%x ",
1509 __virtscr
->alines
[i
]->flags
);
1510 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1511 __CTRACE(__CTRACE_REFRESH
, "%c",
1512 __virtscr
->alines
[i
]->line
[j
].ch
);
1513 __CTRACE(__CTRACE_REFRESH
, "\n");
1514 __CTRACE(__CTRACE_REFRESH
, " attr:");
1515 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1516 __CTRACE(__CTRACE_REFRESH
, " %x",
1517 __virtscr
->alines
[i
]->line
[j
].attr
);
1518 __CTRACE(__CTRACE_REFRESH
, "\n");
1523 if (buf
[0].ch
!= ' ') {
1524 for (i
= 0; i
< BLANKSIZE
; i
++) {
1530 if (buf
[0].ch
!= ( wchar_t )btowc(( int ) curscr
->bch
)) {
1531 for (i
= 0; i
< BLANKSIZE
; i
++) {
1532 buf
[i
].ch
= ( wchar_t )btowc(( int ) curscr
->bch
);
1533 if (_cursesi_copy_nsp(curscr
->bnsp
, &buf
[i
]) == ERR
)
1536 SET_WCOL( buf
[ i
], 1 );
1539 #endif /* HAVE_WCHAR */
1541 if (__virtscr
->maxx
!= last_hash_len
) {
1543 for (i
= __virtscr
->maxx
; i
> BLANKSIZE
; i
-= BLANKSIZE
) {
1544 blank_hash
= __hash_more(buf
, sizeof(buf
), blank_hash
);
1546 blank_hash
= __hash_more((char *)(void *)buf
,
1547 i
* sizeof(buf
[0]), blank_hash
);
1548 /* cache result in static data - screen width doesn't change often */
1549 last_hash_len
= __virtscr
->maxx
;
1550 last_hash
= blank_hash
;
1552 blank_hash
= last_hash
;
1555 * Perform the rotation to maintain the consistency of curscr.
1556 * This is hairy since we are doing an *in place* rotation.
1557 * Invariants of the loop:
1558 * - I is the index of the current line.
1559 * - Target is the index of the target of line i.
1560 * - Tmp1 points to current line (i).
1561 * - Tmp2 and points to target line (target);
1562 * - Cur_period is the index of the end of the current period.
1565 * There are 2 major issues here that make this rotation non-trivial:
1566 * 1. Scrolling in a scrolling region bounded by the top
1567 * and bottom regions determined (whose size is sc_region).
1568 * 2. As a result of the use of the mod function, there may be a
1569 * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
1570 * 0 to 2, which then causes all odd lines not to be rotated.
1571 * To remedy this, an index of the end ( = beginning) of the
1572 * current 'period' is kept, cur_period, and when it is reached,
1573 * the next period is started from cur_period + 1 which is
1574 * guaranteed not to have been reached since that would mean that
1575 * all records would have been reached. (think about it...).
1577 * Lines in the rotation can have 3 attributes which are marked on the
1578 * line so that curscr is consistent with the visual screen.
1579 * 1. Not dirty -- lines inside the scrolled block, top region or
1581 * 2. Blank lines -- lines in the differential of the scrolling
1582 * region adjacent to top and bot regions
1583 * depending on scrolling direction.
1584 * 3. Dirty line -- all other lines are marked dirty.
1586 sc_region
= bot
- top
+ 1;
1588 tmp1
= curscr
->alines
[top
];
1590 for (j
= top
; j
<= bot
; j
++) {
1591 target
= (i
- top
+ n
+ sc_region
) % sc_region
+ top
;
1592 tmp2
= curscr
->alines
[target
];
1593 curscr
->alines
[target
] = tmp1
;
1594 /* Mark block as clean and blank out scrolled lines. */
1595 clp
= curscr
->alines
[target
];
1597 __CTRACE(__CTRACE_REFRESH
,
1598 "quickch: n=%d startw=%d curw=%d i = %d target=%d ",
1599 n
, startw
, curw
, i
, target
);
1601 if ((target
>= startw
&& target
< curw
) || target
< top
1604 __CTRACE(__CTRACE_REFRESH
, " notdirty\n");
1606 __virtscr
->alines
[target
]->flags
&= ~__ISDIRTY
;
1608 if ((n
> 0 && target
>= top
&& target
< top
+ n
) ||
1609 (n
< 0 && target
<= bot
&& target
> bot
+ n
)) {
1611 if (clp
->hash
!= blank_hash
||
1612 memcmp(clp
->line
, clp
->line
+ 1,
1613 (__virtscr
->maxx
- 1)
1615 memcmp(clp
->line
, buf
, __LDATASIZE
)) {
1617 if (clp
->hash
!= blank_hash
1618 || linecmp(clp
->line
, clp
->line
+ 1,
1619 (unsigned int) (__virtscr
->maxx
- 1))
1620 || cellcmp(clp
->line
, buf
)) {
1621 #endif /* HAVE_WCHAR */
1622 for (i
= __virtscr
->maxx
;
1625 (void) memcpy(clp
->line
+ i
-
1626 BLANKSIZE
, buf
, sizeof(buf
));
1628 (void) memcpy(clp
->line
, buf
, i
*
1631 __CTRACE(__CTRACE_REFRESH
,
1632 " blanked out: dirty\n");
1634 clp
->hash
= blank_hash
;
1635 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1638 __CTRACE(__CTRACE_REFRESH
,
1639 " -- blank line already: dirty\n");
1641 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1645 __CTRACE(__CTRACE_REFRESH
, " -- dirty\n");
1647 __touchline(__virtscr
, target
, 0, (int) __virtscr
->maxx
- 1);
1649 if (target
== cur_period
) {
1651 tmp1
= curscr
->alines
[i
];
1659 __CTRACE(__CTRACE_REFRESH
, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
1660 for (i
= 0; i
< curscr
->maxy
; i
++) {
1661 __CTRACE(__CTRACE_REFRESH
, "C: %d:", i
);
1662 for (j
= 0; j
< curscr
->maxx
; j
++)
1663 __CTRACE(__CTRACE_REFRESH
, "%c",
1664 curscr
->alines
[i
]->line
[j
].ch
);
1665 __CTRACE(__CTRACE_REFRESH
, "\n");
1666 __CTRACE(__CTRACE_REFRESH
, "W: %d:", i
);
1667 for (j
= 0; j
< __virtscr
->maxx
; j
++)
1668 __CTRACE(__CTRACE_REFRESH
, "%c",
1669 __virtscr
->alines
[i
]->line
[j
].ch
);
1670 __CTRACE(__CTRACE_REFRESH
, "\n");
1674 scrolln(starts
, startw
, curs
, bot
, top
);
1679 * Scroll n lines, where n is starts - startw.
1681 static void /* ARGSUSED */
1682 scrolln(starts
, startw
, curs
, bot
, top
)
1683 int starts
, startw
, curs
, bot
, top
;
1689 n
= starts
- startw
;
1693 * The initial tests that set __noqch don't let us reach here unless
1694 * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
1695 * scrolling can only shift the entire scrolling region, not just a
1696 * part of it, which means that the quickch() routine is going to be
1697 * sadly disappointed in us if we don't have cs as well.
1699 * If cs, ho and SF/sf are set, can use the scrolling region. Because
1700 * the cursor position after cs is undefined, we need ho which gives us
1701 * the ability to move to somewhere without knowledge of the current
1702 * location of the cursor. Still call __mvcur() anyway, to update its
1703 * idea of where the cursor is.
1705 * When the scrolling region has been set, the cursor has to be at the
1706 * last line of the region to make the scroll happen.
1708 * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr
1709 * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not
1710 * SF/SR. So, if we're scrolling almost all of the screen, try and use
1711 * AL/DL, otherwise use the scrolling region. The "almost all" is a
1712 * shameless hack for vi.
1715 if (change_scroll_region
!= NULL
&& cursor_home
!= NULL
&&
1716 (parm_index
!= NULL
||
1717 ((parm_insert_line
== NULL
|| parm_delete_line
== NULL
||
1718 top
> 3 || bot
+ 3 < __virtscr
->maxy
) &&
1719 scroll_forward
!= NULL
)))
1721 tputs(tiparm(change_scroll_region
, top
, bot
),
1723 __mvcur(oy
, ox
, 0, 0, 1);
1724 tputs(cursor_home
, 0, __cputchar
);
1725 __mvcur(0, 0, bot
, 0, 1);
1726 if (parm_index
!= NULL
)
1727 tputs(tiparm(parm_index
, n
),
1730 for (i
= 0; i
< n
; i
++)
1731 tputs(scroll_forward
, 0, __cputchar
);
1732 tputs(tiparm(change_scroll_region
,
1733 0, (int) __virtscr
->maxy
- 1), 0, __cputchar
);
1734 __mvcur(bot
, 0, 0, 0, 1);
1735 tputs(cursor_home
, 0, __cputchar
);
1736 __mvcur(0, 0, oy
, ox
, 1);
1740 /* Scroll up the block. */
1741 if (parm_index
!= NULL
&& top
== 0) {
1742 __mvcur(oy
, ox
, bot
, 0, 1);
1743 tputs(tiparm(parm_index
, n
), 0, __cputchar
);
1745 if (parm_delete_line
!= NULL
) {
1746 __mvcur(oy
, ox
, top
, 0, 1);
1747 tputs(tiparm(parm_delete_line
, n
),
1750 if (delete_line
!= NULL
) {
1751 __mvcur(oy
, ox
, top
, 0, 1);
1752 for (i
= 0; i
< n
; i
++)
1756 if (scroll_forward
!= NULL
&& top
== 0) {
1757 __mvcur(oy
, ox
, bot
, 0, 1);
1758 for (i
= 0; i
< n
; i
++)
1759 tputs(scroll_forward
, 0,
1764 /* Push down the bottom region. */
1765 __mvcur(top
, 0, bot
- n
+ 1, 0, 1);
1766 if (parm_insert_line
!= NULL
)
1767 tputs(tiparm(parm_insert_line
, n
), 0, __cputchar
);
1769 if (insert_line
!= NULL
)
1770 for (i
= 0; i
< n
; i
++)
1771 tputs(insert_line
, 0, __cputchar
);
1774 __mvcur(bot
- n
+ 1, 0, oy
, ox
, 1);
1780 * If cs, ho and SR/sr are set, can use the scrolling region.
1781 * See the above comments for details.
1783 if (change_scroll_region
!= NULL
&& cursor_home
!= NULL
&&
1784 (parm_rindex
!= NULL
||
1785 ((parm_insert_line
== NULL
|| parm_delete_line
== NULL
||
1787 bot
+ 3 < __virtscr
->maxy
) && scroll_reverse
!= NULL
)))
1789 tputs(tiparm(change_scroll_region
, top
, bot
),
1791 __mvcur(oy
, ox
, 0, 0, 1);
1792 tputs(cursor_home
, 0, __cputchar
);
1793 __mvcur(0, 0, top
, 0, 1);
1795 if (parm_rindex
!= NULL
)
1796 tputs(tiparm(parm_rindex
, -n
),
1799 for (i
= n
; i
< 0; i
++)
1800 tputs(scroll_reverse
, 0, __cputchar
);
1801 tputs(tiparm(change_scroll_region
,
1802 0, (int) __virtscr
->maxy
- 1), 0, __cputchar
);
1803 __mvcur(top
, 0, 0, 0, 1);
1804 tputs(cursor_home
, 0, __cputchar
);
1805 __mvcur(0, 0, oy
, ox
, 1);
1809 /* Preserve the bottom lines. */
1810 __mvcur(oy
, ox
, bot
+ n
+ 1, 0, 1);
1811 if (parm_rindex
!= NULL
&& bot
== __virtscr
->maxy
)
1812 tputs(tiparm(parm_rindex
, -n
), 0, __cputchar
);
1814 if (parm_delete_line
!= NULL
)
1815 tputs(tiparm(parm_delete_line
, -n
),
1818 if (delete_line
!= NULL
)
1819 for (i
= n
; i
< 0; i
++)
1823 if (scroll_reverse
!= NULL
&&
1824 bot
== __virtscr
->maxy
)
1825 for (i
= n
; i
< 0; i
++)
1826 tputs(scroll_reverse
, 0,
1831 /* Scroll the block down. */
1832 __mvcur(bot
+ n
+ 1, 0, top
, 0, 1);
1833 if (parm_insert_line
!= NULL
)
1834 tputs(tiparm(parm_insert_line
, -n
), 0, __cputchar
);
1836 if (insert_line
!= NULL
)
1837 for (i
= n
; i
< 0; i
++)
1838 tputs(insert_line
, 0, __cputchar
);
1841 __mvcur(top
, 0, oy
, ox
, 1);
1847 * Unset attributes on curscr. Leave standout, attribute and colour
1848 * modes if necessary (!ms). Always leave altcharset (xterm at least
1849 * ignores a cursor move if we don't).
1852 __unsetattr(int checkms
)
1857 if (!move_standout_mode
) {
1865 __CTRACE(__CTRACE_REFRESH
,
1866 "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n",
1867 checkms
, move_standout_mode
? "TRUE" : "FALSE", curscr
->wattr
);
1871 * Don't leave the screen in standout mode (check against ms). Check
1872 * to see if we also turn off underscore, attributes and colour.
1874 if (curscr
->wattr
& __STANDOUT
&& isms
) {
1875 tputs(exit_standout_mode
, 0, __cputchar
);
1876 curscr
->wattr
&= __mask_se
;
1879 * Don't leave the screen in underscore mode (check against ms).
1880 * Check to see if we also turn off attributes. Assume that we
1881 * also turn off colour.
1883 if (curscr
->wattr
& __UNDERSCORE
&& isms
) {
1884 tputs(exit_underline_mode
, 0, __cputchar
);
1885 curscr
->wattr
&= __mask_ue
;
1888 * Don't leave the screen with attributes set (check against ms).
1889 * Assume that also turn off colour.
1891 if (curscr
->wattr
& __TERMATTR
&& isms
) {
1892 tputs(exit_attribute_mode
, 0, __cputchar
);
1893 curscr
->wattr
&= __mask_me
;
1895 /* Don't leave the screen with altcharset set (don't check ms). */
1896 if (curscr
->wattr
& __ALTCHARSET
) {
1897 tputs(exit_alt_charset_mode
, 0, __cputchar
);
1898 curscr
->wattr
&= ~__ALTCHARSET
;
1900 /* Don't leave the screen with colour set (check against ms). */
1901 if (__using_color
&& isms
)
1902 __unset_color(curscr
);
1906 /* compare two cells on screen, must have the same forground/background,
1907 * and the same sequence of non-spacing characters */
1909 cellcmp( __LDATA
*x
, __LDATA
*y
)
1911 nschar_t
*xnp
= x
->nsp
, *ynp
= y
->nsp
;
1912 int ret
= ( x
->ch
== y
->ch
) & ( x
->attr
== y
->attr
);
1918 if (( xnp
&& !ynp
) || ( !xnp
&& ynp
))
1921 while ( xnp
&& ynp
) {
1922 if ( xnp
->ch
!= ynp
->ch
)
1927 return ( !xnp
&& !ynp
);
1930 /* compare two line segments */
1932 linecmp( __LDATA
*xl
, __LDATA
*yl
, size_t len
)
1935 __LDATA
*xp
= xl
, *yp
= yl
;
1937 for ( i
= 0; i
< len
; i
++, xp
++, yp
++ ) {
1938 if ( !cellcmp( xp
, yp
))
1945 * Output the non-spacing characters associated with the given character
1946 * cell to the screen.
1950 __cursesi_putnsp(nschar_t
*nsp
, const int wy
, const int wx
)
1954 /* this shuts up gcc warnings about wx and wy not being used */
1960 __cputwchar((int) p
->ch
);
1962 __CTRACE(__CTRACE_REFRESH
,
1963 "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n",
1970 #endif /* HAVE_WCHAR */