lib_refresh.c revision 97049
1/****************************************************************************
2 * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc.              *
3 *                                                                          *
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:                 *
11 *                                                                          *
12 * The above copyright notice and this permission notice shall be included  *
13 * in all copies or substantial portions of the Software.                   *
14 *                                                                          *
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.                               *
22 *                                                                          *
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       *
26 * authorization.                                                           *
27 ****************************************************************************/
28
29/****************************************************************************
30 *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31 *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32 ****************************************************************************/
33
34/*
35 *	lib_refresh.c
36 *
37 *	The routines wrefresh() and wnoutrefresh().
38 *
39 */
40
41#include <curses.priv.h>
42
43MODULE_ID("$Id: lib_refresh.c,v 1.31 2001/12/19 01:06:41 tom Exp $")
44
45NCURSES_EXPORT(int)
46wrefresh(WINDOW *win)
47{
48    int code;
49
50    T((T_CALLED("wrefresh(%p)"), win));
51
52    if (win == curscr) {
53	curscr->_clear = TRUE;
54	code = doupdate();
55    } else if ((code = wnoutrefresh(win)) == OK) {
56	if (win->_clear)
57	    newscr->_clear = TRUE;
58	code = doupdate();
59	/*
60	 * Reset the clearok() flag in case it was set for the special
61	 * case in hardscroll.c (if we don't reset it here, we'll get 2
62	 * refreshes because the flag is copied from stdscr to newscr).
63	 * Resetting the flag shouldn't do any harm, anyway.
64	 */
65	win->_clear = FALSE;
66    }
67    returnCode(code);
68}
69
70NCURSES_EXPORT(int)
71wnoutrefresh(WINDOW *win)
72{
73    NCURSES_SIZE_T limit_x;
74    NCURSES_SIZE_T i, j;
75    NCURSES_SIZE_T begx;
76    NCURSES_SIZE_T begy;
77    NCURSES_SIZE_T m, n;
78#if USE_SCROLL_HINTS
79    bool wide;
80#endif
81
82    T((T_CALLED("wnoutrefresh(%p)"), win));
83#ifdef TRACE
84    if (_nc_tracing & TRACE_UPDATE)
85	_tracedump("...win", win);
86#endif /* TRACE */
87
88    /*
89     * This function will break badly if we try to refresh a pad.
90     */
91    if ((win == 0)
92	|| (win->_flags & _ISPAD))
93	returnCode(ERR);
94
95    /* put them here so "win == 0" won't break our code */
96    begx = win->_begx;
97    begy = win->_begy;
98
99    newscr->_nc_bkgd = win->_nc_bkgd;
100    newscr->_attrs = win->_attrs;
101
102    /* merge in change information from all subwindows of this window */
103    wsyncdown(win);
104
105#if USE_SCROLL_HINTS
106    /*
107     * For pure efficiency, we'd want to transfer scrolling information
108     * from the window to newscr whenever the window is wide enough that
109     * its update will dominate the cost of the update for the horizontal
110     * band of newscr that it occupies.  Unfortunately, this threshold
111     * tends to be complex to estimate, and in any case scrolling the
112     * whole band and rewriting the parts outside win's image would look
113     * really ugly.  So.  What we do is consider the window "wide" if it
114     * either (a) occupies the whole width of newscr, or (b) occupies
115     * all but at most one column on either vertical edge of the screen
116     * (this caters to fussy people who put boxes around full-screen
117     * windows).  Note that changing this formula will not break any code,
118     * merely change the costs of various update cases.
119     */
120    wide = (begx <= 1 && win->_maxx >= (newscr->_maxx - 1));
121#endif
122
123    win->_flags &= ~_HASMOVED;
124
125    /*
126     * Microtweaking alert!  This double loop is one of the genuine
127     * hot spots in the code.  Even gcc doesn't seem to do enough
128     * common-subexpression chunking to make it really tense,
129     * so we'll force the issue.
130     */
131
132    /* limit(n) */
133    limit_x = win->_maxx;
134    /* limit(j) */
135    if (limit_x > win->_maxx)
136	limit_x = win->_maxx;
137
138    for (i = 0, m = begy + win->_yoffset;
139	 i <= win->_maxy && m <= newscr->_maxy;
140	 i++, m++) {
141	register struct ldat *nline = &newscr->_line[m];
142	register struct ldat *oline = &win->_line[i];
143
144	if (oline->firstchar != _NOCHANGE) {
145	    int last = oline->lastchar;
146
147	    if (last > limit_x)
148		last = limit_x;
149
150	    for (j = oline->firstchar, n = j + begx; j <= last; j++, n++) {
151		if (!CharEq(oline->text[j], nline->text[n])) {
152		    nline->text[n] = oline->text[j];
153		    CHANGED_CELL(nline, n);
154		}
155	    }
156
157	}
158#if USE_SCROLL_HINTS
159	if (wide) {
160	    int oind = oline->oldindex;
161
162	    nline->oldindex = (oind == _NEWINDEX) ? _NEWINDEX : begy + oind
163		+ win->_yoffset;
164	}
165#endif /* USE_SCROLL_HINTS */
166
167	oline->firstchar = oline->lastchar = _NOCHANGE;
168	if_USE_SCROLL_HINTS(oline->oldindex = i);
169    }
170
171    if (win->_clear) {
172	win->_clear = FALSE;
173	newscr->_clear = TRUE;
174    }
175
176    if (!win->_leaveok) {
177	newscr->_cury = win->_cury + win->_begy + win->_yoffset;
178	newscr->_curx = win->_curx + win->_begx;
179    }
180    newscr->_leaveok = win->_leaveok;
181
182#ifdef TRACE
183    if (_nc_tracing & TRACE_UPDATE)
184	_tracedump("newscr", newscr);
185#endif /* TRACE */
186    returnCode(OK);
187}
188