xref: /aosp_15_r20/external/coreboot/payloads/libpayload/curses/PDCurses/pdcurses/overlay.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 RCSID("$Id: overlay.c,v 1.36 2008/07/14 12:35:23 wmcbrine Exp $")
6 
7 /*man-start**************************************************************
8 
9   Name:                                                         overlay
10 
11   Synopsis:
12         int overlay(const WINDOW *src_w, WINDOW *dst_w)
13         int overwrite(const WINDOW *src_w, WINDOW *dst_w)
14         int copywin(const WINDOW *src_w, WINDOW *dst_w, int src_tr,
15                     int src_tc, int dst_tr, int dst_tc, int dst_br,
16                     int dst_bc, bool overlay)
17 
18   Description:
19         overlay() and overwrite() copy all the text from src_w into
20         dst_w. The windows need not be the same size. Those characters
21         in the source window that intersect with the destination window
22         are copied, so that the characters appear in the same physical
23         position on the screen. The difference between the two functions
24         is that overlay() is non-destructive (blanks are not copied)
25         while overwrite() is destructive (blanks are copied).
26 
27         copywin() is similar, but doesn't require that the two windows
28         overlap. The arguments src_tc and src_tr specify the top left
29         corner of the region to be copied. dst_tc, dst_tr, dst_br, and
30         dst_bc specify the region within the destination window to copy
31         to. The argument "overlay", if TRUE, indicates that the copy is
32         done non-destructively (as in overlay()); blanks in the source
33         window are not copied to the destination window. When overlay is
34         FALSE, blanks are copied.
35 
36   Return Value:
37         All functions return OK on success and ERR on error.
38 
39   Portability                                X/Open    BSD    SYS V
40         overlay                                 Y       Y       Y
41         overwrite                               Y       Y       Y
42         copywin                                 Y       -      3.0
43 
44 **man-end****************************************************************/
45 
46 /* Thanks to Andreas Otte <venn@@uni-paderborn.de> for the
47    corrected overlay()/overwrite() behavior. */
48 
_copy_win(const WINDOW * src_w,WINDOW * dst_w,int src_tr,int src_tc,int src_br,int src_bc,int dst_tr,int dst_tc,bool _overlay)49 static int _copy_win(const WINDOW *src_w, WINDOW *dst_w, int src_tr,
50                      int src_tc, int src_br, int src_bc, int dst_tr,
51                      int dst_tc, bool _overlay)
52 {
53     int col, line, y1, fc, *minchng, *maxchng;
54     chtype *w1ptr, *w2ptr;
55 
56     int lc = 0;
57     int xdiff = src_bc - src_tc;
58     int ydiff = src_br - src_tr;
59 
60     if (!src_w || !dst_w)
61         return ERR;
62 
63     minchng = dst_w->_firstch;
64     maxchng = dst_w->_lastch;
65 
66     for (y1 = 0; y1 < dst_tr; y1++)
67     {
68         minchng++;
69         maxchng++;
70     }
71 
72     for (line = 0; line < ydiff; line++)
73     {
74         w1ptr = src_w->_y[line + src_tr] + src_tc;
75         w2ptr = dst_w->_y[line + dst_tr] + dst_tc;
76 
77         fc = _NO_CHANGE;
78 
79         for (col = 0; col < xdiff; col++)
80         {
81             if ((*w1ptr) != (*w2ptr) &&
82                 !((*w1ptr & A_CHARTEXT) == ' ' && _overlay))
83             {
84                 *w2ptr = *w1ptr;
85 
86                 if (fc == _NO_CHANGE)
87                     fc = col + dst_tc;
88 
89                 lc = col + dst_tc;
90             }
91 
92             w1ptr++;
93             w2ptr++;
94         }
95 
96         if (*minchng == _NO_CHANGE)
97         {
98             *minchng = fc;
99             *maxchng = lc;
100         }
101         else if (fc != _NO_CHANGE)
102         {
103             if (fc < *minchng)
104                 *minchng = fc;
105             if (lc > *maxchng)
106                 *maxchng = lc;
107         }
108 
109         minchng++;
110         maxchng++;
111     }
112 
113     return OK;
114 }
115 
overlay(const WINDOW * src_w,WINDOW * dst_w)116 int overlay(const WINDOW *src_w, WINDOW *dst_w)
117 {
118     int first_line, first_col, last_line, last_col;
119     int src_start_x, src_start_y, dst_start_x, dst_start_y;
120     int xdiff, ydiff;
121 
122     PDC_LOG(("overlay() - called\n"));
123 
124     if (!src_w || !dst_w)
125         return ERR;
126 
127     first_col = max(dst_w->_begx, src_w->_begx);
128     first_line = max(dst_w->_begy, src_w->_begy);
129 
130     last_col = min(src_w->_begx + src_w->_maxx, dst_w->_begx + dst_w->_maxx);
131     last_line = min(src_w->_begy + src_w->_maxy, dst_w->_begy + dst_w->_maxy);
132 
133     /* determine the overlapping region of the two windows in real
134        coordinates */
135 
136     /* if no overlapping region, do nothing */
137 
138     if ((last_col < first_col) || (last_line < first_line))
139         return OK;
140 
141     /* size of overlapping region */
142 
143     xdiff = last_col - first_col;
144     ydiff = last_line - first_line;
145 
146     if (src_w->_begx <= dst_w->_begx)
147     {
148         src_start_x = dst_w->_begx - src_w->_begx;
149         dst_start_x = 0;
150     }
151     else
152     {
153         dst_start_x = src_w->_begx - dst_w->_begx;
154         src_start_x = 0;
155     }
156 
157     if (src_w->_begy <= dst_w->_begy)
158     {
159         src_start_y = dst_w->_begy - src_w->_begy;
160         dst_start_y = 0;
161     }
162     else
163     {
164         dst_start_y = src_w->_begy - dst_w->_begy;
165         src_start_y = 0;
166     }
167 
168     return _copy_win(src_w, dst_w, src_start_y, src_start_x,
169                      src_start_y + ydiff, src_start_x + xdiff,
170                      dst_start_y, dst_start_x, TRUE);
171 }
172 
overwrite(const WINDOW * src_w,WINDOW * dst_w)173 int overwrite(const WINDOW *src_w, WINDOW *dst_w)
174 {
175     int first_line, first_col, last_line, last_col;
176     int src_start_x, src_start_y, dst_start_x, dst_start_y;
177     int xdiff, ydiff;
178 
179     PDC_LOG(("overwrite() - called\n"));
180 
181     if (!src_w || !dst_w)
182         return ERR;
183 
184     first_col = max(dst_w->_begx, src_w->_begx);
185     first_line = max(dst_w->_begy, src_w->_begy);
186 
187     last_col = min(src_w->_begx + src_w->_maxx, dst_w->_begx + dst_w->_maxx);
188     last_line = min(src_w->_begy + src_w->_maxy, dst_w->_begy + dst_w->_maxy);
189 
190     /* determine the overlapping region of the two windows in real
191        coordinates */
192 
193     /* if no overlapping region, do nothing */
194 
195     if ((last_col < first_col) || (last_line < first_line))
196         return OK;
197 
198     /* size of overlapping region */
199 
200     xdiff = last_col - first_col;
201     ydiff = last_line - first_line;
202 
203     if (src_w->_begx <= dst_w->_begx)
204     {
205         src_start_x = dst_w->_begx - src_w->_begx;
206         dst_start_x = 0;
207     }
208     else
209     {
210         dst_start_x = src_w->_begx - dst_w->_begx;
211         src_start_x = 0;
212     }
213 
214     if (src_w->_begy <= dst_w->_begy)
215     {
216         src_start_y = dst_w->_begy - src_w->_begy;
217         dst_start_y = 0;
218     }
219     else
220     {
221         dst_start_y = src_w->_begy - dst_w->_begy;
222         src_start_y = 0;
223     }
224 
225     return _copy_win(src_w, dst_w, src_start_y, src_start_x,
226                      src_start_y + ydiff, src_start_x + xdiff,
227                      dst_start_y, dst_start_x, FALSE);
228 }
229 
copywin(const WINDOW * src_w,WINDOW * dst_w,int src_tr,int src_tc,int dst_tr,int dst_tc,int dst_br,int dst_bc,int _overlay)230 int copywin(const WINDOW *src_w, WINDOW *dst_w, int src_tr, int src_tc,
231             int dst_tr, int dst_tc, int dst_br, int dst_bc, int _overlay)
232 {
233     int src_end_x, src_end_y;
234     int src_rows, src_cols, dst_rows, dst_cols;
235     int min_rows, min_cols;
236 
237     PDC_LOG(("copywin() - called\n"));
238 
239     if (!src_w || !dst_w || dst_w == curscr || dst_br > dst_w->_maxy
240         || dst_bc > dst_w->_maxx || dst_tr < 0 || dst_tc < 0)
241         return ERR;
242 
243     src_rows = src_w->_maxy - src_tr;
244     src_cols = src_w->_maxx - src_tc;
245     dst_rows = dst_br - dst_tr + 1;
246     dst_cols = dst_bc - dst_tc + 1;
247 
248     min_rows = min(src_rows, dst_rows);
249     min_cols = min(src_cols, dst_cols);
250 
251     src_end_y = src_tr + min_rows;
252     src_end_x = src_tc + min_cols;
253 
254     return _copy_win(src_w, dst_w, src_tr, src_tc, src_end_y, src_end_x,
255                      dst_tr, dst_tc, _overlay);
256 }
257