xref: /aosp_15_r20/external/coreboot/payloads/libpayload/curses/PDCurses/pdcurses/refresh.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 RCSID("$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:
20         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
26         is left at the location of the window's cursor.
27 
28         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
37         doupdate() only once.
38 
39         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
42         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 
wnoutrefresh(WINDOW * win)59 int 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 
82             /* ignore areas on the outside that are marked as changed,
83                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 
98                 first += begx;
99                 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 
doupdate(void)127 int 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 
wrefresh(WINDOW * win)220 int 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 
refresh(void)242 int refresh(void)
243 {
244     PDC_LOG(("refresh() - called\n"));
245 
246     return wrefresh(stdscr);
247 }
248 
wredrawln(WINDOW * win,int start,int num)249 int 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 
redrawwin(WINDOW * win)268 int 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 }
277