xref: /minix/lib/libcurses/touchwin.c (revision 00b67f09)
1 /*	$NetBSD: touchwin.c,v 1.27 2013/12/06 11:23:47 blymn Exp $	*/
2 
3 /*
4  * Copyright (c) 1981, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
18  *
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
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)touchwin.c	8.2 (Berkeley) 5/4/94";
36 #else
37 __RCSID("$NetBSD: touchwin.c,v 1.27 2013/12/06 11:23:47 blymn Exp $");
38 #endif
39 #endif				/* not lint */
40 
41 #include "curses.h"
42 #include "curses_private.h"
43 
44 static int _cursesi_touchline_force(WINDOW *, int, int, int, int);
45 
46 /*
47  * is_linetouched --
48  *	Indicate if line has been touched or not.
49  */
50 bool
51 is_linetouched(WINDOW *win, int line)
52 {
53 	if (line > win->maxy)
54 		return FALSE;
55 
56 	return ((win->alines[line]->flags & __ISDIRTY) != 0);
57 }
58 
59 /*
60  * touchline --
61  *	Touch count lines starting at start.  This is the SUS v2 compliant
62  *	version.
63  */
64 int
65 touchline(WINDOW *win, int start, int count)
66 {
67 #ifdef DEBUG
68 	__CTRACE(__CTRACE_LINE, "touchline: (%p, %d, %d)\n", win, start, count);
69 #endif
70 	return wtouchln(win, start, count, 1);
71 }
72 
73 /*
74  * wredrawln --
75  *	Mark count lines starting at start as corrupted.  Implemented using
76  *	wtouchln().
77  */
78 int wredrawln(WINDOW *win, int start, int count)
79 {
80 #ifdef DEBUG
81 	__CTRACE(__CTRACE_LINE, "wredrawln: (%p, %d, %d)\n", win, start, count);
82 #endif
83 	return wtouchln(win, start, count, 1);
84 }
85 
86 /*
87  * is_wintouched --
88  *	Check if the window has been touched.
89  */
90 bool
91 is_wintouched(WINDOW *win)
92 {
93 	int y, maxy;
94 
95 	maxy = win->maxy;
96 	for (y = 0; y < maxy; y++) {
97 		if (is_linetouched(win, y) == TRUE)
98 			return TRUE;
99 	}
100 
101 	return FALSE;
102 }
103 
104 /*
105  * touchwin --
106  *	Make it look like the whole window has been changed.
107  */
108 int
109 touchwin(WINDOW *win)
110 {
111 #ifdef DEBUG
112 	__CTRACE(__CTRACE_LINE, "touchwin: (%p)\n", win);
113 #endif
114 	return wtouchln(win, 0, win->maxy, 1);
115 }
116 
117 /*
118  * redrawwin --
119  *	Mark entire window as corrupted.  Implemented using wtouchln().
120  */
121 int
122 redrawwin(WINDOW *win)
123 {
124 #ifdef DEBUG
125 	__CTRACE(__CTRACE_LINE, "redrawwin: (%p)\n", win);
126 #endif
127 	return wtouchln(win, 0, win->maxy, 1);
128 }
129 
130 /*
131  * untouchwin --
132  *	 Make it look like the window has not been changed.
133  */
134 int
135 untouchwin(WINDOW *win)
136 {
137 #ifdef DEBUG
138 	__CTRACE(__CTRACE_LINE, "untouchwin: (%p)\n", win);
139 #endif
140 	return wtouchln(win, 0, win->maxy, 0);
141 }
142 
143 /*
144  * wtouchln --
145  *	If changed is 1 then touch n lines starting at line.  If changed
146  *	is 0 then mark the lines as unchanged.
147  */
148 int
149 wtouchln(WINDOW *win, int line, int n, int changed)
150 {
151 	int	y;
152 	__LINE	*wlp;
153 
154 #ifdef DEBUG
155 	__CTRACE(__CTRACE_LINE, "wtouchln: (%p) %d, %d, %d\n",
156 	    win, line, n, changed);
157 #endif
158 	if (line + n > win->maxy)
159 		line = win->maxy - n;
160 	for (y = line; y < line + n; y++) {
161 		if (changed == 1)
162 			_cursesi_touchline_force(win, y, 0,
163 			    (int) win->maxx - 1, 1);
164 		else {
165 			wlp = win->alines[y];
166 			if (*wlp->firstchp >= win->ch_off &&
167 			    *wlp->firstchp < win->maxx + win->ch_off)
168 				*wlp->firstchp = win->maxx + win->ch_off;
169 			if (*wlp->lastchp >= win->ch_off &&
170 			    *wlp->lastchp < win->maxx + win->ch_off)
171 				*wlp->lastchp = win->ch_off;
172 			wlp->flags &= ~(__ISDIRTY | __ISFORCED);
173 		}
174 	}
175 
176 	return OK;
177 }
178 
179 int
180 __touchwin(WINDOW *win)
181 {
182 	int	 y, maxy;
183 
184 #ifdef DEBUG
185 	__CTRACE(__CTRACE_LINE, "__touchwin: (%p)\n", win);
186 #endif
187 	maxy = win->maxy;
188 	for (y = 0; y < maxy; y++)
189 		__touchline(win, y, 0, (int) win->maxx - 1);
190 	return (OK);
191 }
192 
193 int
194 __touchline(WINDOW *win, int y, int sx, int ex)
195 {
196 	return (_cursesi_touchline_force(win, y, sx, ex, 0));
197 }
198 
199 /*
200  * Touch line y on window win starting from column sx and ending at
201  * column ex.  If force is 1 then we mark this line as a forced update
202  * which will bypass screen optimisation in the refresh code to rewrite
203  * this line unconditionally (even if refresh thinks the screen matches
204  * what is in the virtscr)
205  */
206 static int
207 _cursesi_touchline_force(WINDOW *win, int y, int sx, int ex, int force)
208 {
209 #ifdef DEBUG
210 	__CTRACE(__CTRACE_LINE, "__touchline: (%p, %d, %d, %d)\n",
211 	    win, y, sx, ex);
212 	__CTRACE(__CTRACE_LINE, "__touchline: first = %d, last = %d\n",
213 	    *win->alines[y]->firstchp, *win->alines[y]->lastchp);
214 #endif
215 	sx += win->ch_off;
216 	ex += win->ch_off;
217 	win->alines[y]->flags |= __ISDIRTY;
218 	if (force == 1)
219 		win->alines[y]->flags |= __ISFORCED;
220 	/* firstchp/lastchp are shared between parent window and sub-window. */
221 	if (*win->alines[y]->firstchp > sx)
222 		*win->alines[y]->firstchp = sx;
223 	if (*win->alines[y]->lastchp < ex)
224 		*win->alines[y]->lastchp = ex;
225 #ifdef DEBUG
226 	__CTRACE(__CTRACE_LINE, "__touchline: first = %d, last = %d\n",
227 	    *win->alines[y]->firstchp, *win->alines[y]->lastchp);
228 #endif
229 	return (OK);
230 }
231 
232 void
233 wsyncup(WINDOW *win)
234 {
235 
236 	do {
237 		__touchwin(win);
238 		win = win->orig;
239 	} while (win);
240 }
241 
242 void
243 wsyncdown(WINDOW *win)
244 {
245 	WINDOW *w = win->orig;
246 
247 	while (w) {
248 		if (is_wintouched(w)) {
249 			__touchwin(win);
250 			break;
251 		}
252 		w = w->orig;
253 	}
254 }
255