xref: /netbsd-src/lib/libcurses/refresh.c (revision 61f282557f0bc41c0b762c629a2f4c14be8b7591)
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 char	*nsp, *csp, *ce;
173 	reg short	wx, lch, y;
174 	reg int		nlsp, clsp;	/* last space in lines		*/
175 
176 	wx = win->_firstch[wy] - win->_ch_off;
177 	if (wx >= win->_maxx)
178 		return OK;
179 	else if (wx < 0)
180 		wx = 0;
181 	lch = win->_lastch[wy] - win->_ch_off;
182 	if (lch < 0)
183 		return OK;
184 	else if (lch >= win->_maxx)
185 		lch = win->_maxx - 1;;
186 	y = wy + win->_begy;
187 
188 	if (curwin)
189 		csp = " ";
190 	else
191 		csp = &curscr->_y[wy + win->_begy][wx + win->_begx];
192 
193 	nsp = &win->_y[wy][wx];
194 	if (CE && !curwin) {
195 		for (ce = &win->_y[wy][win->_maxx - 1]; *ce == ' '; ce--)
196 			if (ce <= win->_y[wy])
197 				break;
198 		nlsp = ce - win->_y[wy];
199 	}
200 
201 	if (!curwin)
202 		ce = CE;
203 	else
204 		ce = NULL;
205 
206 	while (wx <= lch) {
207 		if (*nsp != *csp) {
208 			domvcur(ly, lx, y, wx + win->_begx);
209 # ifdef DEBUG
210 			fprintf(outf, "MAKECH: 1: wx = %d, lx = %d\n", wx, lx);
211 # endif
212 			ly = y;
213 			lx = wx + win->_begx;
214 			while (*nsp != *csp && wx <= lch) {
215 				if (ce != NULL && wx >= nlsp && *nsp == ' ') {
216 					/*
217 					 * check for clear to end-of-line
218 					 */
219 					ce = &curscr->_y[ly][COLS - 1];
220 					while (*ce == ' ')
221 						if (ce-- <= csp)
222 							break;
223 					clsp = ce - curscr->_y[ly] - win->_begx;
224 # ifdef DEBUG
225 					fprintf(outf, "MAKECH: clsp = %d, nlsp = %d\n", clsp, nlsp);
226 # endif
227 					if (clsp - nlsp >= strlen(CE)
228 					    && clsp < win->_maxx) {
229 # ifdef DEBUG
230 						fprintf(outf, "MAKECH: using CE\n");
231 # endif
232 						_puts(CE);
233 						lx = wx + win->_begx;
234 						while (wx++ <= clsp)
235 							*csp++ = ' ';
236 						return OK;
237 					}
238 					ce = NULL;
239 				}
240 				/*
241 				 * enter/exit standout mode as appropriate
242 				 */
243 				if (SO && (*nsp&_STANDOUT) != (curscr->_flags&_STANDOUT)) {
244 					if (*nsp & _STANDOUT) {
245 						_puts(SO);
246 						curscr->_flags |= _STANDOUT;
247 					}
248 					else {
249 						_puts(SE);
250 						curscr->_flags &= ~_STANDOUT;
251 					}
252 				}
253 				wx++;
254 				if (wx >= win->_maxx && wy == win->_maxy - 1)
255 					if (win->_scroll) {
256 					    if ((curscr->_flags&_STANDOUT) &&
257 					        (win->_flags & _ENDLINE))
258 						    if (!MS) {
259 							_puts(SE);
260 							curscr->_flags &= ~_STANDOUT;
261 						    }
262 					    if (!curwin)
263 						_putchar((*csp = *nsp) & 0177);
264 					    else
265 						_putchar(*nsp & 0177);
266 					    if (win->_flags&_FULLWIN && !curwin)
267 						scroll(curscr);
268 					    ly = win->_begy+win->_cury;
269 					    lx = win->_begx+win->_curx;
270 					    return OK;
271 					}
272 					else if (win->_flags&_SCROLLWIN) {
273 					    lx = --wx;
274 					    return ERR;
275 					}
276 				if (!curwin)
277 					_putchar((*csp++ = *nsp) & 0177);
278 				else
279 					_putchar(*nsp & 0177);
280 # ifdef FULLDEBUG
281 				fprintf(outf,
282 					"MAKECH:putchar(%c)\n", *nsp & 0177);
283 # endif
284 				if (UC && (*nsp & _STANDOUT)) {
285 					_putchar('\b');
286 					_puts(UC);
287 				}
288 				nsp++;
289 			}
290 # ifdef DEBUG
291 			fprintf(outf, "MAKECH: 2: wx = %d, lx = %d\n", wx, lx);
292 # endif
293 			if (lx == wx + win->_begx)	/* if no change */
294 				break;
295 			lx = wx + win->_begx;
296 			if (lx >= COLS && AM) {
297 				lx = 0;
298 				ly++;
299 				/*
300 				 * xn glitch: chomps a newline after auto-wrap.
301 				 * we just feed it now and forget about it.
302 				 */
303 				if (XN) {
304 					_putchar('\n');
305 					_putchar('\r');
306 				}
307 			}
308 		}
309 		else if (wx <= lch)
310 			while (*nsp == *csp && wx <= lch) {
311 				nsp++;
312 				if (!curwin)
313 					csp++;
314 				++wx;
315 			}
316 		else
317 			break;
318 # ifdef DEBUG
319 		fprintf(outf, "MAKECH: 3: wx = %d, lx = %d\n", wx, lx);
320 # endif
321 	}
322 	return OK;
323 }
324 
325 /*
326  * perform a mvcur, leaving standout mode if necessary
327  */
328 STATIC
329 domvcur(oy, ox, ny, nx)
330 int	oy, ox, ny, nx; {
331 
332 	if (curscr->_flags & _STANDOUT && !MS) {
333 		_puts(SE);
334 		curscr->_flags &= ~_STANDOUT;
335 	}
336 	mvcur(oy, ox, ny, nx);
337 }
338