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