xref: /netbsd-src/lib/libcurses/refresh.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
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[] = "@(#)refresh.c	5.5 (Berkeley) 3/3/91";
36 #endif /* not lint */
37 
38 /*
39  * make the current screen look like "win" over the area coverd by
40  * win.
41  */
42 
43 # include	"curses.ext"
44 
45 # ifdef DEBUG
46 # define	STATIC
47 # else
48 # define	STATIC	static
49 # endif
50 
51 STATIC short	ly, lx;
52 
53 STATIC bool	curwin;
54 
55 WINDOW	*_win = NULL;
56 
57 STATIC int	domvcur(), makech();
58 
59 wrefresh(win)
60 reg WINDOW	*win;
61 {
62 	reg short	wy;
63 	reg int		retval;
64 	reg WINDOW	*orig;
65 
66 	/*
67 	 * make sure were in visual state
68 	 */
69 	if (_endwin) {
70 		_puts(VS);
71 		_puts(TI);
72 		_endwin = FALSE;
73 	}
74 
75 	/*
76 	 * initialize loop parameters
77 	 */
78 
79 	ly = curscr->_cury;
80 	lx = curscr->_curx;
81 	wy = 0;
82 	_win = win;
83 	curwin = (win == curscr);
84 
85 	if (win->_clear || curscr->_clear || curwin) {
86 		if ((win->_flags & _FULLWIN) || curscr->_clear) {
87 			_puts(CL);
88 			ly = 0;
89 			lx = 0;
90 			if (!curwin) {
91 				curscr->_clear = FALSE;
92 				curscr->_cury = 0;
93 				curscr->_curx = 0;
94 				werase(curscr);
95 			}
96 			touchwin(win);
97 		}
98 		win->_clear = FALSE;
99 	}
100 	if (!CA) {
101 		if (win->_curx != 0)
102 			_putchar('\n');
103 		if (!curwin)
104 			werase(curscr);
105 	}
106 # ifdef DEBUG
107 	fprintf(outf, "REFRESH(%0.2o): curwin = %d\n", win, curwin);
108 	fprintf(outf, "REFRESH:\n\tfirstch\tlastch\n");
109 # endif
110 	for (wy = 0; wy < win->_maxy; wy++) {
111 # ifdef DEBUG
112 		fprintf(outf, "%d\t%d\t%d\n", wy, win->_firstch[wy],
113 			win->_lastch[wy]);
114 # endif
115 		if (win->_firstch[wy] != _NOCHANGE)
116 			if (makech(win, wy) == ERR)
117 				return ERR;
118 			else {
119 				if (win->_firstch[wy] >= win->_ch_off)
120 					win->_firstch[wy] = win->_maxx +
121 							    win->_ch_off;
122 				if (win->_lastch[wy] < win->_maxx +
123 						       win->_ch_off)
124 					win->_lastch[wy] = win->_ch_off;
125 				if (win->_lastch[wy] < win->_firstch[wy])
126 					win->_firstch[wy] = _NOCHANGE;
127 			}
128 # ifdef DEBUG
129 		fprintf(outf, "\t%d\t%d\n", win->_firstch[wy],
130 			win->_lastch[wy]);
131 # endif
132 	}
133 
134 	if (win == curscr)
135 		domvcur(ly, lx, win->_cury, win->_curx);
136 	else {
137 		if (win->_leave) {
138 			curscr->_cury = ly;
139 			curscr->_curx = lx;
140 			ly -= win->_begy;
141 			lx -= win->_begx;
142 			if (ly >= 0 && ly < win->_maxy && lx >= 0 &&
143 			    lx < win->_maxx) {
144 				win->_cury = ly;
145 				win->_curx = lx;
146 			}
147 			else
148 				win->_cury = win->_curx = 0;
149 		}
150 		else {
151 			domvcur(ly, lx, win->_cury + win->_begy,
152 				win->_curx + win->_begx);
153 			curscr->_cury = win->_cury + win->_begy;
154 			curscr->_curx = win->_curx + win->_begx;
155 		}
156 	}
157 	retval = OK;
158 ret:
159 	_win = NULL;
160 	fflush(stdout);
161 	return retval;
162 }
163 
164 /*
165  * make a change on the screen
166  */
167 STATIC
168 makech(win, wy)
169 reg WINDOW	*win;
170 short		wy;
171 {
172 	reg chtype      *nsp, *csp, *ce;
173 	reg short	wx, lch, y;
174 	reg int		nlsp, clsp;	/* last space in lines		*/
175 	char *ce_tcap;
176 	static chtype blank[] = {' ','\0'};
177 
178 	wx = win->_firstch[wy] - win->_ch_off;
179 	if (wx >= win->_maxx)
180 		return OK;
181 	else if (wx < 0)
182 		wx = 0;
183 	lch = win->_lastch[wy] - win->_ch_off;
184 	if (lch < 0)
185 		return OK;
186 	else if (lch >= win->_maxx)
187 		lch = win->_maxx - 1;;
188 	y = wy + win->_begy;
189 
190 	if (curwin)
191 		csp = blank;
192 	else
193 		csp = &curscr->_y[wy + win->_begy][wx + win->_begx];
194 
195 	nsp = &win->_y[wy][wx];
196 	if (CE && !curwin) {
197 		for (ce = &win->_y[wy][win->_maxx - 1]; *ce == ' '; ce--)
198 			if (ce <= win->_y[wy])
199 				break;
200 		nlsp = ce - win->_y[wy];
201 	}
202 
203 	if (!curwin)
204 		ce_tcap = CE;
205 	else
206 		ce_tcap = NULL;
207 
208 	while (wx <= lch) {
209 		if (*nsp != *csp) {
210 			domvcur(ly, lx, y, wx + win->_begx);
211 # ifdef DEBUG
212 			fprintf(outf, "MAKECH: 1: wx = %d, lx = %d\n", wx, lx);
213 # endif
214 			ly = y;
215 			lx = wx + win->_begx;
216 			while (*nsp != *csp && wx <= lch) {
217 				if (ce_tcap != NULL && wx >= nlsp && *nsp == ' ') {
218 					/*
219 					 * check for clear to end-of-line
220 					 */
221 					ce = &curscr->_y[ly][COLS - 1];
222 					while (*ce == ' ')
223 						if (ce-- <= csp)
224 							break;
225 					clsp = ce - curscr->_y[ly] - win->_begx;
226 # ifdef DEBUG
227 					fprintf(outf, "MAKECH: clsp = %d, nlsp = %d\n", clsp, nlsp);
228 # endif
229 					if (clsp - nlsp >= strlen(CE)
230 					    && clsp < win->_maxx) {
231 # ifdef DEBUG
232 						fprintf(outf, "MAKECH: using CE\n");
233 # endif
234 						_puts(CE);
235 						lx = wx + win->_begx;
236 						while (wx++ <= clsp)
237 							*csp++ = ' ';
238 						return OK;
239 					}
240 					ce_tcap = NULL;
241 				}
242 				/*
243 				 * enter/exit standout mode as appropriate
244 				 */
245 				if (SO && (*nsp&_STANDOUT) != (curscr->_flags&_STANDOUT)) {
246 					if (*nsp & _STANDOUT) {
247 						_puts(SO);
248 						curscr->_flags |= _STANDOUT;
249 					}
250 					else {
251 						_puts(SE);
252 						curscr->_flags &= ~_STANDOUT;
253 					}
254 				}
255 				wx++;
256 				if (wx >= win->_maxx && wy == win->_maxy - 1)
257 					if (win->_scroll) {
258 					    if ((curscr->_flags&_STANDOUT) &&
259 					        (win->_flags & _ENDLINE))
260 						    if (!MS) {
261 							_puts(SE);
262 							curscr->_flags &= ~_STANDOUT;
263 						    }
264 					    if (!curwin)
265 						_putchar((*csp = *nsp));
266 					    else
267 						_putchar(*nsp);
268 					    if (win->_flags&_FULLWIN && !curwin)
269 						scroll(curscr);
270 					    ly = win->_begy+win->_cury;
271 					    lx = win->_begx+win->_curx;
272 					    return OK;
273 					}
274 					else if (win->_flags&_SCROLLWIN) {
275 					    lx = --wx;
276 					    return ERR;
277 					}
278 				if (!curwin)
279 					_putchar((*csp++ = *nsp));
280 				else
281 					_putchar(*nsp);
282 # ifdef FULLDEBUG
283 				fprintf(outf,
284 					"MAKECH:putchar(%c)\n", *nsp);
285 # endif
286 				if (UC && (*nsp & _STANDOUT)) {
287 					_putchar('\b');
288 					_puts(UC);
289 				}
290 				nsp++;
291 			}
292 # ifdef DEBUG
293 			fprintf(outf, "MAKECH: 2: wx = %d, lx = %d\n", wx, lx);
294 # endif
295 			if (lx == wx + win->_begx)	/* if no change */
296 				break;
297 			lx = wx + win->_begx;
298 			if (lx >= COLS && AM) {
299 				lx = 0;
300 				ly++;
301 				/*
302 				 * xn glitch: chomps a newline after auto-wrap.
303 				 * we just feed it now and forget about it.
304 				 */
305 				if (XN) {
306 					_putchar('\n');
307 					_putchar('\r');
308 				}
309 			}
310 		}
311 		else if (wx <= lch)
312 			while (*nsp == *csp && wx <= lch) {
313 				nsp++;
314 				if (!curwin)
315 					csp++;
316 				++wx;
317 			}
318 		else
319 			break;
320 # ifdef DEBUG
321 		fprintf(outf, "MAKECH: 3: wx = %d, lx = %d\n", wx, lx);
322 # endif
323 	}
324 	return OK;
325 }
326 
327 /*
328  * perform a mvcur, leaving standout mode if necessary
329  */
330 STATIC
331 domvcur(oy, ox, ny, nx)
332 int	oy, ox, ny, nx; {
333 
334 	if (curscr->_flags & _STANDOUT && !MS) {
335 		_puts(SE);
336 		curscr->_flags &= ~_STANDOUT;
337 	}
338 	mvcur(oy, ox, ny, nx);
339 }
340