xref: /netbsd/lib/libcurses/touchwin.c (revision 6550d01e)
1 /*	$NetBSD: touchwin.c,v 1.26 2010/02/23 19:48:26 drochner 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.26 2010/02/23 19:48:26 drochner Exp $");
38 #endif
39 #endif				/* not lint */
40 
41 #include "curses.h"
42 #include "curses_private.h"
43 
44 /*
45  * is_linetouched --
46  *	Indicate if line has been touched or not.
47  */
48 bool
49 is_linetouched(WINDOW *win, int line)
50 {
51 	if (line > win->maxy)
52 		return FALSE;
53 
54 	return ((win->alines[line]->flags & __ISDIRTY) != 0);
55 }
56 
57 /*
58  * touchline --
59  *	Touch count lines starting at start.  This is the SUS v2 compliant
60  *	version.
61  */
62 int
63 touchline(WINDOW *win, int start, int count)
64 {
65 #ifdef DEBUG
66 	__CTRACE(__CTRACE_LINE, "touchline: (%p, %d, %d)\n", win, start, count);
67 #endif
68 	return wtouchln(win, start, count, 1);
69 }
70 
71 /*
72  * wredrawln --
73  *	Mark count lines starting at start as corrupted.  Implemented using
74  *	wtouchln().
75  */
76 int wredrawln(WINDOW *win, int start, int count)
77 {
78 #ifdef DEBUG
79 	__CTRACE(__CTRACE_LINE, "wredrawln: (%p, %d, %d)\n", win, start, count);
80 #endif
81 	return wtouchln(win, start, count, 1);
82 }
83 
84 /*
85  * is_wintouched --
86  *	Check if the window has been touched.
87  */
88 bool
89 is_wintouched(WINDOW *win)
90 {
91 	int y, maxy;
92 
93 	maxy = win->maxy;
94 	for (y = 0; y < maxy; y++) {
95 		if (is_linetouched(win, y) == TRUE)
96 			return TRUE;
97 	}
98 
99 	return FALSE;
100 }
101 
102 /*
103  * touchwin --
104  *	Make it look like the whole window has been changed.
105  */
106 int
107 touchwin(WINDOW *win)
108 {
109 #ifdef DEBUG
110 	__CTRACE(__CTRACE_LINE, "touchwin: (%p)\n", win);
111 #endif
112 	return wtouchln(win, 0, win->maxy, 1);
113 }
114 
115 /*
116  * redrawwin --
117  *	Mark entire window as corrupted.  Implemented using wtouchln().
118  */
119 int
120 redrawwin(WINDOW *win)
121 {
122 #ifdef DEBUG
123 	__CTRACE(__CTRACE_LINE, "redrawwin: (%p)\n", win);
124 #endif
125 	return wtouchln(win, 0, win->maxy, 1);
126 }
127 
128 /*
129  * untouchwin --
130  *	 Make it look like the window has not been changed.
131  */
132 int
133 untouchwin(WINDOW *win)
134 {
135 #ifdef DEBUG
136 	__CTRACE(__CTRACE_LINE, "untouchwin: (%p)\n", win);
137 #endif
138 	return wtouchln(win, 0, win->maxy, 0);
139 }
140 
141 /*
142  * wtouchln --
143  *	If changed is 1 then touch n lines starting at line.  If changed
144  *	is 0 then mark the lines as unchanged.
145  */
146 int
147 wtouchln(WINDOW *win, int line, int n, int changed)
148 {
149 	int	y;
150 	__LINE	*wlp;
151 
152 #ifdef DEBUG
153 	__CTRACE(__CTRACE_LINE, "wtouchln: (%p) %d, %d, %d\n",
154 	    win, line, n, changed);
155 #endif
156 	if (line + n > win->maxy)
157 		line = win->maxy - n;
158 	for (y = line; y < line + n; y++) {
159 		if (changed == 1)
160 			__touchline(win, y, 0, (int) win->maxx - 1);
161 		else {
162 			wlp = win->alines[y];
163 			if (*wlp->firstchp >= win->ch_off &&
164 			    *wlp->firstchp < win->maxx + win->ch_off)
165 				*wlp->firstchp = win->maxx + win->ch_off;
166 			if (*wlp->lastchp >= win->ch_off &&
167 			    *wlp->lastchp < win->maxx + win->ch_off)
168 				*wlp->lastchp = win->ch_off;
169 			wlp->flags &= ~__ISDIRTY;
170 		}
171 	}
172 
173 	return OK;
174 }
175 
176 int
177 __touchwin(WINDOW *win)
178 {
179 	int	 y, maxy;
180 
181 #ifdef DEBUG
182 	__CTRACE(__CTRACE_LINE, "__touchwin: (%p)\n", win);
183 #endif
184 	maxy = win->maxy;
185 	for (y = 0; y < maxy; y++)
186 		__touchline(win, y, 0, (int) win->maxx - 1);
187 	return (OK);
188 }
189 
190 int
191 __touchline(WINDOW *win, int y, int sx, int ex)
192 {
193 #ifdef DEBUG
194 	__CTRACE(__CTRACE_LINE, "__touchline: (%p, %d, %d, %d)\n",
195 	    win, y, sx, ex);
196 	__CTRACE(__CTRACE_LINE, "__touchline: first = %d, last = %d\n",
197 	    *win->alines[y]->firstchp, *win->alines[y]->lastchp);
198 #endif
199 	sx += win->ch_off;
200 	ex += win->ch_off;
201 	if (!(win->alines[y]->flags & __ISDIRTY))
202 		win->alines[y]->flags |= __ISDIRTY;
203 	/* firstchp/lastchp are shared between parent window and sub-window. */
204 	if (*win->alines[y]->firstchp > sx)
205 		*win->alines[y]->firstchp = sx;
206 	if (*win->alines[y]->lastchp < ex)
207 		*win->alines[y]->lastchp = ex;
208 #ifdef DEBUG
209 	__CTRACE(__CTRACE_LINE, "__touchline: first = %d, last = %d\n",
210 	    *win->alines[y]->firstchp, *win->alines[y]->lastchp);
211 #endif
212 	return (OK);
213 }
214 
215 void
216 wsyncup(WINDOW *win)
217 {
218 
219 	do {
220 		touchwin(win);
221 		win = win->orig;
222 	} while (win);
223 }
224 
225 void
226 wsyncdown(WINDOW *win)
227 {
228 	WINDOW *w = win->orig;
229 
230 	while (w) {
231 		if (is_wintouched(w)) {
232 			touchwin(win);
233 			break;
234 		}
235 		w = w->orig;
236 	}
237 }
238