blob: da4bb76edd54ff4da721a223e24ed8e74a4fe6f7 [file] [log] [blame]
Patrick Georgi3b77b722011-07-07 15:41:53 +02001/* Public Domain Curses */
2
3#include <curspriv.h>
4
5RCSID("$Id: refresh.c,v 1.56 2008/07/13 16:08:18 wmcbrine Exp $")
6
7/*man-start**************************************************************
8
9 Name: refresh
10
11 Synopsis:
12 int refresh(void);
13 int wrefresh(WINDOW *win);
14 int wnoutrefresh(WINDOW *win);
15 int doupdate(void);
16 int redrawwin(WINDOW *win);
17 int wredrawln(WINDOW *win, int beg_line, int num_lines);
18
19 Description:
Stefan Reinauere11835e2011-10-31 12:54:00 -070020 wrefresh() copies the named window to the physical terminal
21 screen, taking into account what is already there in order to
22 optimize cursor movement. refresh() does the same, using stdscr.
23 These routines must be called to get any output on the terminal,
24 as other routines only manipulate data structures. Unless
25 leaveok() has been enabled, the physical cursor of the terminal
Patrick Georgi3b77b722011-07-07 15:41:53 +020026 is left at the location of the window's cursor.
27
Stefan Reinauere11835e2011-10-31 12:54:00 -070028 wnoutrefresh() and doupdate() allow multiple updates with more
29 efficiency than wrefresh() alone. wrefresh() works by first
30 calling wnoutrefresh(), which copies the named window to the
31 virtual screen. It then calls doupdate(), which compares the
32 virtual screen to the physical screen and does the actual
33 update. A series of calls to wrefresh() will result in
34 alternating calls to wnoutrefresh() and doupdate(), causing
35 several bursts of output to the screen. By first calling
36 wnoutrefresh() for each window, it is then possible to call
Patrick Georgi3b77b722011-07-07 15:41:53 +020037 doupdate() only once.
38
Stefan Reinauere11835e2011-10-31 12:54:00 -070039 In PDCurses, redrawwin() is equivalent to touchwin(), and
40 wredrawln() is the same as touchline(). In some other curses
41 implementations, there's a subtle distinction, but it has no
Patrick Georgi3b77b722011-07-07 15:41:53 +020042 meaning in PDCurses.
43
44 Return Value:
45 All functions return OK on success and ERR on error.
46
47 Portability X/Open BSD SYS V
48 refresh Y Y Y
49 wrefresh Y Y Y
50 wnoutrefresh Y Y Y
51 doupdate Y Y Y
52 redrawwin Y - 4.0
53 wredrawln Y - 4.0
54
55**man-end****************************************************************/
56
57#include <string.h>
58
59int wnoutrefresh(WINDOW *win)
60{
61 int begy, begx; /* window's place on screen */
62 int i, j;
63
64 PDC_LOG(("wnoutrefresh() - called: win=%p\n", win));
65
66 if ( !win || (win->_flags & (_PAD|_SUBPAD)) )
67 return ERR;
68
69 begy = win->_begy;
70 begx = win->_begx;
71
72 for (i = 0, j = begy; i < win->_maxy; i++, j++)
73 {
74 if (win->_firstch[i] != _NO_CHANGE)
75 {
76 chtype *src = win->_y[i];
77 chtype *dest = curscr->_y[j] + begx;
78
79 int first = win->_firstch[i]; /* first changed */
80 int last = win->_lastch[i]; /* last changed */
81
Stefan Reinauere11835e2011-10-31 12:54:00 -070082 /* ignore areas on the outside that are marked as changed,
Patrick Georgi3b77b722011-07-07 15:41:53 +020083 but really aren't */
84
85 while (first <= last && src[first] == dest[first])
86 first++;
87
88 while (last >= first && src[last] == dest[last])
89 last--;
90
91 /* if any have really changed... */
92
93 if (first <= last)
94 {
95 memcpy(dest + first, src + first,
96 (last - first + 1) * sizeof(chtype));
97
Stefan Reinauere11835e2011-10-31 12:54:00 -070098 first += begx;
Patrick Georgi3b77b722011-07-07 15:41:53 +020099 last += begx;
100
101 if (first < curscr->_firstch[j] ||
102 curscr->_firstch[j] == _NO_CHANGE)
103 curscr->_firstch[j] = first;
104
105 if (last > curscr->_lastch[j])
106 curscr->_lastch[j] = last;
107 }
108
109 win->_firstch[i] = _NO_CHANGE; /* updated now */
110 }
111
112 win->_lastch[i] = _NO_CHANGE; /* updated now */
113 }
114
115 if (win->_clear)
116 win->_clear = FALSE;
117
118 if (!win->_leaveit)
119 {
120 curscr->_cury = win->_cury + begy;
121 curscr->_curx = win->_curx + begx;
122 }
123
124 return OK;
125}
126
127int doupdate(void)
128{
129 int y;
130 bool clearall;
131
132 PDC_LOG(("doupdate() - called\n"));
133
134 if (!curscr)
135 return ERR;
136
137 if (isendwin()) /* coming back after endwin() called */
138 {
139 reset_prog_mode();
140 clearall = TRUE;
141 SP->alive = TRUE; /* so isendwin() result is correct */
142 }
143 else
144 clearall = curscr->_clear;
145
146 for (y = 0; y < SP->lines; y++)
147 {
148 PDC_LOG(("doupdate() - Transforming line %d of %d: %s\n",
149 y, SP->lines, (curscr->_firstch[y] != _NO_CHANGE) ?
150 "Yes" : "No"));
151
152 if (clearall || curscr->_firstch[y] != _NO_CHANGE)
153 {
154 int first, last;
155
156 chtype *src = curscr->_y[y];
157 chtype *dest = pdc_lastscr->_y[y];
158
159 if (clearall)
160 {
161 first = 0;
162 last = COLS - 1;
163 }
164 else
165 {
166 first = curscr->_firstch[y];
167 last = curscr->_lastch[y];
168 }
169
170 while (first <= last)
171 {
172 int len = 0;
173
174 /* build up a run of changed cells; if two runs are
175 separated by a single unchanged cell, ignore the
176 break */
177
178 if (clearall)
179 len = last - first + 1;
180 else
181 while (first + len <= last &&
182 (src[first + len] != dest[first + len] ||
183 (len && first + len < last &&
184 src[first + len + 1] != dest[first + len + 1])
185 )
186 )
187 len++;
188
189 /* update the screen, and pdc_lastscr */
190
191 if (len)
192 {
193 PDC_transform_line(y, first, len, src + first);
194 memcpy(dest + first, src + first, len * sizeof(chtype));
195 first += len;
196 }
197
198 /* skip over runs of unchanged cells */
199
200 while (first <= last && src[first] == dest[first])
201 first++;
202 }
203
204 curscr->_firstch[y] = _NO_CHANGE;
205 curscr->_lastch[y] = _NO_CHANGE;
206 }
207 }
208
209 curscr->_clear = FALSE;
210
211 if (SP->visibility)
212 PDC_gotoyx(curscr->_cury, curscr->_curx);
213
214 SP->cursrow = curscr->_cury;
215 SP->curscol = curscr->_curx;
216
217 return OK;
218}
219
220int wrefresh(WINDOW *win)
221{
222 bool save_clear;
223
224 PDC_LOG(("wrefresh() - called\n"));
225
226 if ( !win || (win->_flags & (_PAD|_SUBPAD)) )
227 return ERR;
228
229 save_clear = win->_clear;
230
231 if (win == curscr)
232 curscr->_clear = TRUE;
233 else
234 wnoutrefresh(win);
235
236 if (save_clear && win->_maxy == SP->lines && win->_maxx == SP->cols)
237 curscr->_clear = TRUE;
238
239 return doupdate();
240}
241
242int refresh(void)
243{
244 PDC_LOG(("refresh() - called\n"));
245
246 return wrefresh(stdscr);
247}
248
249int wredrawln(WINDOW *win, int start, int num)
250{
251 int i;
252
253 PDC_LOG(("wredrawln() - called: win=%p start=%d num=%d\n",
254 win, start, num));
255
256 if (!win || start > win->_maxy || start + num > win->_maxy)
257 return ERR;
258
259 for (i = start; i < start + num; i++)
260 {
261 win->_firstch[i] = 0;
262 win->_lastch[i] = win->_maxx - 1;
263 }
264
265 return OK;
266}
267
268int redrawwin(WINDOW *win)
269{
270 PDC_LOG(("redrawwin() - called: win=%p\n", win));
271
272 if (!win)
273 return ERR;
274
275 return wredrawln(win, 0, win->_maxy);
276}