xref: /netbsd-src/lib/libcurses/refresh.c (revision e9d867ef5010fbab8d48045c13025636f5cd7479)
1 /*
2  * Copyright (c) 1981 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 /*static char sccsid[] = "from: @(#)refresh.c	5.5 (Berkeley) 3/3/91";*/
36 static char rcsid[] = "$Id: refresh.c,v 1.3 1993/08/01 18:35:26 mycroft Exp $";
37 #endif /* not lint */
38 
39 /*
40  * make the current screen look like "win" over the area coverd by
41  * win.
42  */
43 
44 # include	"curses.ext"
45 
46 # ifdef DEBUG
47 # define	STATIC
48 # else
49 # define	STATIC	static
50 # endif
51 
52 STATIC short	ly, lx;
53 
54 STATIC bool	curwin;
55 
56 WINDOW	*_win = NULL;
57 
58 STATIC int	domvcur(), makech();
59 
60 wrefresh(win)
61 reg WINDOW	*win;
62 {
63 	reg short	wy;
64 	reg int		retval;
65 	reg WINDOW	*orig;
66 
67 	/*
68 	 * make sure were in visual state
69 	 */
70 	if (_endwin) {
71 		_puts(VS);
72 		_puts(TI);
73 		_endwin = FALSE;
74 	}
75 
76 	/*
77 	 * initialize loop parameters
78 	 */
79 
80 	ly = curscr->_cury;
81 	lx = curscr->_curx;
82 	wy = 0;
83 	_win = win;
84 	curwin = (win == curscr);
85 
86 	if (win->_clear || curscr->_clear || curwin) {
87 		if ((win->_flags & _FULLWIN) || curscr->_clear) {
88 			_puts(CL);
89 			ly = 0;
90 			lx = 0;
91 			if (!curwin) {
92 				curscr->_clear = FALSE;
93 				curscr->_cury = 0;
94 				curscr->_curx = 0;
95 				werase(curscr);
96 			}
97 			touchwin(win);
98 		}
99 		win->_clear = FALSE;
100 	}
101 	if (!CA) {
102 		if (win->_curx != 0)
103 			_putchar('\n');
104 		if (!curwin)
105 			werase(curscr);
106 	}
107 # ifdef DEBUG
108 	fprintf(outf, "REFRESH(%0.2o): curwin = %d\n", win, curwin);
109 	fprintf(outf, "REFRESH:\n\tfirstch\tlastch\n");
110 # endif
111 	for (wy = 0; wy < win->_maxy; wy++) {
112 # ifdef DEBUG
113 		fprintf(outf, "%d\t%d\t%d\n", wy, win->_firstch[wy],
114 			win->_lastch[wy]);
115 # endif
116 		if (win->_firstch[wy] != _NOCHANGE)
117 			if (makech(win, wy) == ERR)
118 				return ERR;
119 			else {
120 				if (win->_firstch[wy] >= win->_ch_off)
121 					win->_firstch[wy] = win->_maxx +
122 							    win->_ch_off;
123 				if (win->_lastch[wy] < win->_maxx +
124 						       win->_ch_off)
125 					win->_lastch[wy] = win->_ch_off;
126 				if (win->_lastch[wy] < win->_firstch[wy])
127 					win->_firstch[wy] = _NOCHANGE;
128 			}
129 # ifdef DEBUG
130 		fprintf(outf, "\t%d\t%d\n", win->_firstch[wy],
131 			win->_lastch[wy]);
132 # endif
133 	}
134 
135 	if (win == curscr)
136 		domvcur(ly, lx, win->_cury, win->_curx);
137 	else {
138 		if (win->_leave) {
139 			curscr->_cury = ly;
140 			curscr->_curx = lx;
141 			ly -= win->_begy;
142 			lx -= win->_begx;
143 			if (ly >= 0 && ly < win->_maxy && lx >= 0 &&
144 			    lx < win->_maxx) {
145 				win->_cury = ly;
146 				win->_curx = lx;
147 			}
148 			else
149 				win->_cury = win->_curx = 0;
150 		}
151 		else {
152 			domvcur(ly, lx, win->_cury + win->_begy,
153 				win->_curx + win->_begx);
154 			curscr->_cury = win->_cury + win->_begy;
155 			curscr->_curx = win->_curx + win->_begx;
156 		}
157 	}
158 	retval = OK;
159 ret:
160 	_win = NULL;
161 	fflush(stdout);
162 	return retval;
163 }
164 
165 /*
166  * make a change on the screen
167  */
168 STATIC
169 makech(win, wy)
170 reg WINDOW	*win;
171 short		wy;
172 {
173 	reg chtype      *nsp, *csp, *ce;
174 	reg short	wx, lch, y;
175 	reg int		nlsp, clsp;	/* last space in lines		*/
176 	char *ce_tcap;
177 	static chtype blank[] = {' ','\0'};
178 
179 	wx = win->_firstch[wy] - win->_ch_off;
180 	if (wx >= win->_maxx)
181 		return OK;
182 	else if (wx < 0)
183 		wx = 0;
184 	lch = win->_lastch[wy] - win->_ch_off;
185 	if (lch < 0)
186 		return OK;
187 	else if (lch >= win->_maxx)
188 		lch = win->_maxx - 1;;
189 	y = wy + win->_begy;
190 
191 	if (curwin)
192 		csp = blank;
193 	else
194 		csp = &curscr->_y[wy + win->_begy][wx + win->_begx];
195 
196 	nsp = &win->_y[wy][wx];
197 	if (CE && !curwin) {
198 		for (ce = &win->_y[wy][win->_maxx - 1]; *ce == ' '; ce--)
199 			if (ce <= win->_y[wy])
200 				break;
201 		nlsp = ce - win->_y[wy];
202 	}
203 
204 	if (!curwin)
205 		ce_tcap = CE;
206 	else
207 		ce_tcap = NULL;
208 
209 	while (wx <= lch) {
210 		if (*nsp != *csp) {
211 			domvcur(ly, lx, y, wx + win->_begx);
212 # ifdef DEBUG
213 			fprintf(outf, "MAKECH: 1: wx = %d, lx = %d\n", wx, lx);
214 # endif
215 			ly = y;
216 			lx = wx + win->_begx;
217 			while (*nsp != *csp && wx <= lch) {
218 				if (ce_tcap != NULL && wx >= nlsp && *nsp == ' ') {
219 					/*
220 					 * check for clear to end-of-line
221 					 */
222 					ce = &curscr->_y[ly][COLS - 1];
223 					while (*ce == ' ')
224 						if (ce-- <= csp)
225 							break;
226 					clsp = ce - curscr->_y[ly] - win->_begx;
227 # ifdef DEBUG
228 					fprintf(outf, "MAKECH: clsp = %d, nlsp = %d\n", clsp, nlsp);
229 # endif
230 					if (clsp - nlsp >= strlen(CE)
231 					    && clsp < win->_maxx) {
232 # ifdef DEBUG
233 						fprintf(outf, "MAKECH: using CE\n");
234 # endif
235 						_puts(CE);
236 						lx = wx + win->_begx;
237 						while (wx++ <= clsp)
238 							*csp++ = ' ';
239 						return OK;
240 					}
241 					ce_tcap = NULL;
242 				}
243 				/*
244 				 * enter/exit standout mode as appropriate
245 				 */
246 				if (SO && (*nsp&_STANDOUT) != (curscr->_flags&_STANDOUT)) {
247 					if (*nsp & _STANDOUT) {
248 						_puts(SO);
249 						curscr->_flags |= _STANDOUT;
250 					}
251 					else {
252 						_puts(SE);
253 						curscr->_flags &= ~_STANDOUT;
254 					}
255 				}
256 				wx++;
257 				if (wx >= win->_maxx && wy == win->_maxy - 1)
258 					if (win->_scroll) {
259 					    if ((curscr->_flags&_STANDOUT) &&
260 					        (win->_flags & _ENDLINE))
261 						    if (!MS) {
262 							_puts(SE);
263 							curscr->_flags &= ~_STANDOUT;
264 						    }
265 					    if (!curwin)
266 						_putchar((*csp = *nsp));
267 					    else
268 						_putchar(*nsp);
269 					    if (win->_flags&_FULLWIN && !curwin)
270 						scroll(curscr);
271 					    ly = win->_begy+win->_cury;
272 					    lx = win->_begx+win->_curx;
273 					    return OK;
274 					}
275 					else if (win->_flags&_SCROLLWIN) {
276 					    lx = --wx;
277 					    return ERR;
278 					}
279 				if (!curwin)
280 					_putchar((*csp++ = *nsp));
281 				else
282 					_putchar(*nsp);
283 # ifdef FULLDEBUG
284 				fprintf(outf,
285 					"MAKECH:putchar(%c)\n", *nsp);
286 # endif
287 				if (UC && (*nsp & _STANDOUT)) {
288 					_putchar('\b');
289 					_puts(UC);
290 				}
291 				nsp++;
292 			}
293 # ifdef DEBUG
294 			fprintf(outf, "MAKECH: 2: wx = %d, lx = %d\n", wx, lx);
295 # endif
296 			if (lx == wx + win->_begx)	/* if no change */
297 				break;
298 			lx = wx + win->_begx;
299 			if (lx >= COLS && AM) {
300 				lx = 0;
301 				ly++;
302 				/*
303 				 * xn glitch: chomps a newline after auto-wrap.
304 				 * we just feed it now and forget about it.
305 				 */
306 				if (XN) {
307 					_putchar('\n');
308 					_putchar('\r');
309 				}
310 			}
311 		}
312 		else if (wx <= lch)
313 			while (*nsp == *csp && wx <= lch) {
314 				nsp++;
315 				if (!curwin)
316 					csp++;
317 				++wx;
318 			}
319 		else
320 			break;
321 # ifdef DEBUG
322 		fprintf(outf, "MAKECH: 3: wx = %d, lx = %d\n", wx, lx);
323 # endif
324 	}
325 	return OK;
326 }
327 
328 /*
329  * perform a mvcur, leaving standout mode if necessary
330  */
331 STATIC
332 domvcur(oy, ox, ny, nx)
333 int	oy, ox, ny, nx; {
334 
335 	if (curscr->_flags & _STANDOUT && !MS) {
336 		_puts(SE);
337 		curscr->_flags &= ~_STANDOUT;
338 	}
339 	mvcur(oy, ox, ny, nx);
340 }
341