1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
31 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
32 * and: Thomas E. Dickey 1996-on *
33 * and: Juergen Pfeifer *
34 ****************************************************************************/
39 * The routines wrefresh() and wnoutrefresh().
43 #include <curses.priv.h>
45 MODULE_ID("$Id: lib_refresh.c,v 1.44 2010/12/19 01:22:58 tom Exp $")
52 SCREEN
*SP_PARM
= _nc_screen_of(win
);
55 T((T_CALLED("wrefresh(%p)"), (void *) win
));
59 } else if (win
== CurScreen(SP_PARM
)) {
60 CurScreen(SP_PARM
)->_clear
= TRUE
;
61 code
= NCURSES_SP_NAME(doupdate
) (NCURSES_SP_ARG
);
62 } else if ((code
= wnoutrefresh(win
)) == OK
) {
64 NewScreen(SP_PARM
)->_clear
= TRUE
;
65 code
= NCURSES_SP_NAME(doupdate
) (NCURSES_SP_ARG
);
67 * Reset the clearok() flag in case it was set for the special
68 * case in hardscroll.c (if we don't reset it here, we'll get 2
69 * refreshes because the flag is copied from stdscr to newscr).
70 * Resetting the flag shouldn't do any harm, anyway.
78 wnoutrefresh(WINDOW
*win
)
89 SCREEN
*SP_PARM
= _nc_screen_of(win
);
92 T((T_CALLED("wnoutrefresh(%p)"), (void *) win
));
94 if (USE_TRACEF(TRACE_UPDATE
)) {
95 _tracedump("...win", win
);
96 _nc_unlock_global(tracef
);
101 * This function will break badly if we try to refresh a pad.
104 || (win
->_flags
& _ISPAD
))
107 /* put them here so "win == 0" won't break our code */
111 NewScreen(SP_PARM
)->_nc_bkgd
= win
->_nc_bkgd
;
112 WINDOW_ATTRS(NewScreen(SP_PARM
)) = WINDOW_ATTRS(win
);
114 /* merge in change information from all subwindows of this window */
119 * For pure efficiency, we'd want to transfer scrolling information
120 * from the window to newscr whenever the window is wide enough that
121 * its update will dominate the cost of the update for the horizontal
122 * band of newscr that it occupies. Unfortunately, this threshold
123 * tends to be complex to estimate, and in any case scrolling the
124 * whole band and rewriting the parts outside win's image would look
125 * really ugly. So. What we do is consider the window "wide" if it
126 * either (a) occupies the whole width of newscr, or (b) occupies
127 * all but at most one column on either vertical edge of the screen
128 * (this caters to fussy people who put boxes around full-screen
129 * windows). Note that changing this formula will not break any code,
130 * merely change the costs of various update cases.
132 wide
= (begx
<= 1 && win
->_maxx
>= (NewScreen(SP_PARM
)->_maxx
- 1));
135 win
->_flags
&= ~_HASMOVED
;
138 * Microtweaking alert! This double loop is one of the genuine
139 * hot spots in the code. Even gcc doesn't seem to do enough
140 * common-subexpression chunking to make it really tense,
141 * so we'll force the issue.
145 limit_x
= win
->_maxx
;
147 if (limit_x
> NewScreen(SP_PARM
)->_maxx
- begx
)
148 limit_x
= NewScreen(SP_PARM
)->_maxx
- begx
;
150 for (src_row
= 0, dst_row
= begy
+ win
->_yoffset
;
151 src_row
<= win
->_maxy
&& dst_row
<= NewScreen(SP_PARM
)->_maxy
;
152 src_row
++, dst_row
++) {
153 struct ldat
*nline
= &(NewScreen(SP_PARM
)->_line
[dst_row
]);
154 struct ldat
*oline
= &win
->_line
[src_row
];
156 if (oline
->firstchar
!= _NOCHANGE
) {
157 int last_src
= oline
->lastchar
;
159 if (last_src
> limit_x
)
162 src_col
= oline
->firstchar
;
163 dst_col
= src_col
+ begx
;
169 * Ensure that we will copy complete multi-column characters
170 * on the left-boundary.
172 if (isWidecExt(oline
->text
[src_col
])) {
173 j
= 1 + dst_col
- WidecExt(oline
->text
[src_col
]);
177 src_col
-= (dst_col
- j
);
183 * Ensure that we will copy complete multi-column characters
184 * on the right-boundary.
187 if (WidecExt(oline
->text
[j
])) {
189 while (j
<= limit_x
) {
190 if (isWidecBase(oline
->text
[j
])) {
201 static cchar_t blank
= BLANK
;
202 int last_dst
= begx
+ ((last_src
< win
->_maxx
)
205 int fix_left
= dst_col
;
206 int fix_right
= last_dst
;
210 * Check for boundary cases where we may overwrite part of a
211 * multi-column character. For those, wipe the remainder of
212 * the character to blanks.
215 if (isWidecExt(nline
->text
[j
])) {
217 * On the left, we only care about multi-column characters
218 * that extend into the changed region.
220 fix_left
= 1 + j
- WidecExt(nline
->text
[j
]);
222 fix_left
= 0; /* only if cell is corrupt */
226 if (WidecExt(nline
->text
[j
]) != 0) {
228 * On the right, any multi-column character is a problem,
229 * unless it happens to be contained in the change, and
230 * ending at the right boundary of the change. The
231 * computation for 'fix_left' accounts for the left-side of
232 * this character. Find the end of the character.
235 while (j
<= NewScreen(SP_PARM
)->_maxx
&&
236 isWidecExt(nline
->text
[j
])) {
242 * The analysis is simpler if we do the clearing afterwards.
245 if (fix_left
< dst_col
|| fix_right
> last_dst
) {
246 for (j
= fix_left
; j
<= fix_right
; ++j
) {
247 nline
->text
[j
] = blank
;
248 CHANGED_CELL(nline
, j
);
254 * Copy the changed text.
256 for (; src_col
<= last_src
; src_col
++, dst_col
++) {
257 if (!CharEq(oline
->text
[src_col
], nline
->text
[dst_col
])) {
258 nline
->text
[dst_col
] = oline
->text
[src_col
];
259 CHANGED_CELL(nline
, dst_col
);
266 int oind
= oline
->oldindex
;
268 nline
->oldindex
= ((oind
== _NEWINDEX
)
270 : (begy
+ oind
+ win
->_yoffset
));
272 #endif /* USE_SCROLL_HINTS */
274 oline
->firstchar
= oline
->lastchar
= _NOCHANGE
;
275 if_USE_SCROLL_HINTS(oline
->oldindex
= src_row
);
280 NewScreen(SP_PARM
)->_clear
= TRUE
;
283 if (!win
->_leaveok
) {
284 NewScreen(SP_PARM
)->_cury
= (NCURSES_SIZE_T
) (win
->_cury
+
285 win
->_begy
+ win
->_yoffset
);
286 NewScreen(SP_PARM
)->_curx
= (NCURSES_SIZE_T
) (win
->_curx
+ win
->_begx
);
288 NewScreen(SP_PARM
)->_leaveok
= win
->_leaveok
;
291 if (USE_TRACEF(TRACE_UPDATE
)) {
292 _tracedump("newscr", NewScreen(SP_PARM
));
293 _nc_unlock_global(tracef
);