xref: /openbsd-src/lib/libcurses/base/lib_refresh.c (revision 62a742911104f98b9185b2c6b6007d9b1c36396c)
1 /*	$OpenBSD: lib_refresh.c,v 1.1 1999/01/18 19:09:57 millert Exp $	*/
2 
3 /****************************************************************************
4  * Copyright (c) 1998 Free Software Foundation, Inc.                        *
5  *                                                                          *
6  * Permission is hereby granted, free of charge, to any person obtaining a  *
7  * copy of this software and associated documentation files (the            *
8  * "Software"), to deal in the Software without restriction, including      *
9  * without limitation the rights to use, copy, modify, merge, publish,      *
10  * distribute, distribute with modifications, sublicense, and/or sell       *
11  * copies of the Software, and to permit persons to whom the Software is    *
12  * furnished to do so, subject to the following conditions:                 *
13  *                                                                          *
14  * The above copyright notice and this permission notice shall be included  *
15  * in all copies or substantial portions of the Software.                   *
16  *                                                                          *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24  *                                                                          *
25  * Except as contained in this notice, the name(s) of the above copyright   *
26  * holders shall not be used in advertising or otherwise to promote the     *
27  * sale, use or other dealings in this Software without prior written       *
28  * authorization.                                                           *
29  ****************************************************************************/
30 
31 /****************************************************************************
32  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
33  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
34  ****************************************************************************/
35 
36 
37 
38 /*
39  *	lib_refresh.c
40  *
41  *	The routines wrefresh() and wnoutrefresh().
42  *
43  */
44 
45 #include <curses.priv.h>
46 
47 MODULE_ID("$From: lib_refresh.c,v 1.23 1998/06/28 00:10:14 tom Exp $")
48 
49 int wrefresh(WINDOW *win)
50 {
51 int code;
52 
53 	T((T_CALLED("wrefresh(%p)"), win));
54 
55 	if (win == curscr) {
56 		curscr->_clear = TRUE;
57 		code = doupdate();
58 	} else if ((code = wnoutrefresh(win)) == OK) {
59 		if (win->_clear)
60 			newscr->_clear = TRUE;
61 		code = doupdate();
62 		/*
63 		 * Reset the clearok() flag in case it was set for the special
64 		 * case in hardscroll.c (if we don't reset it here, we'll get 2
65 		 * refreshes because the flag is copied from stdscr to newscr).
66 		 * Resetting the flag shouldn't do any harm, anyway.
67 		 */
68 		win->_clear = FALSE;
69 	}
70 	returnCode(code);
71 }
72 
73 int wnoutrefresh(WINDOW *win)
74 {
75 short	limit_x;
76 short	i, j;
77 short	begx;
78 short	begy;
79 short	m, n;
80 bool	wide;
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 	/*
100 	 * If 'newscr' has a different background than the window that we're
101 	 * trying to refresh, we'll have to copy the whole thing.
102 	 */
103 	if (win->_bkgd != newscr->_bkgd) {
104 		touchwin(win);
105 		newscr->_bkgd = win->_bkgd;
106 	}
107 	newscr->_attrs = win->_attrs;
108 
109 	/* merge in change information from all subwindows of this window */
110 	wsyncdown(win);
111 
112 	/*
113 	 * For pure efficiency, we'd want to transfer scrolling information
114 	 * from the window to newscr whenever the window is wide enough that
115 	 * its update will dominate the cost of the update for the horizontal
116 	 * band of newscr that it occupies.  Unfortunately, this threshold
117 	 * tends to be complex to estimate, and in any case scrolling the
118 	 * whole band and rewriting the parts outside win's image would look
119 	 * really ugly.  So.  What we do is consider the window "wide" if it
120 	 * either (a) occupies the whole width of newscr, or (b) occupies
121 	 * all but at most one column on either vertical edge of the screen
122 	 * (this caters to fussy people who put boxes around full-screen
123 	 * windows).  Note that changing this formula will not break any code,
124 	 * merely change the costs of various update cases.
125 	 */
126 	wide = (begx <= 1 && win->_maxx >= (newscr->_maxx - 1));
127 
128 	win->_flags &= ~_HASMOVED;
129 
130 	/*
131 	 * Microtweaking alert!  This double loop is one of the genuine
132 	 * hot spots in the code.  Even gcc doesn't seem to do enough
133 	 * common-subexpression chunking to make it really tense,
134 	 * so we'll force the issue.
135 	 */
136 
137 	/* limit(n) */
138 	limit_x = win->_maxx;
139 	/* limit(j) */
140 	if (limit_x > win->_maxx)
141 		limit_x = win->_maxx;
142 
143 	for (i = 0, m = begy + win->_yoffset;
144 	     i <= win->_maxy && m <= newscr->_maxy;
145 	     i++, m++) {
146 		register struct ldat	*nline = &newscr->_line[m];
147 		register struct ldat	*oline = &win->_line[i];
148 
149 		if (oline->firstchar != _NOCHANGE) {
150 			int last = oline->lastchar;
151 
152 			if (last > limit_x)
153 				last = limit_x;
154 
155 			for (j = oline->firstchar, n = j + begx; j <= last; j++, n++) {
156 				if (oline->text[j] != nline->text[n]) {
157 					nline->text[n] = oline->text[j];
158 					CHANGED_CELL(nline, n);
159 				}
160 			}
161 
162 		}
163 
164 #if USE_SCROLL_HINTS
165 		if (wide) {
166 		    int	oind = oline->oldindex;
167 
168 		    nline->oldindex = (oind == _NEWINDEX) ? _NEWINDEX : begy + oind + win->_yoffset;
169 		}
170 #endif /* USE_SCROLL_HINTS */
171 
172 		oline->firstchar = oline->lastchar = _NOCHANGE;
173 		if_USE_SCROLL_HINTS(oline->oldindex = i);
174 	}
175 
176 	if (win->_clear) {
177 		win->_clear = FALSE;
178 		newscr->_clear = TRUE;
179 	}
180 
181 	if (! win->_leaveok) {
182 		newscr->_cury = win->_cury + win->_begy + win->_yoffset;
183 		newscr->_curx = win->_curx + win->_begx;
184 	}
185 	newscr->_leaveok = win->_leaveok;
186 
187 #ifdef TRACE
188 	if (_nc_tracing & TRACE_UPDATE)
189 	    _tracedump("newscr", newscr);
190 #endif /* TRACE */
191 	returnCode(OK);
192 }
193