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