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