1 /* $OpenBSD: lib_overlay.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */
2
3 /****************************************************************************
4 * Copyright 2020 Thomas E. Dickey *
5 * Copyright 1998-2013,2016 Free Software Foundation, Inc. *
6 * *
7 * Permission is hereby granted, free of charge, to any person obtaining a *
8 * copy of this software and associated documentation files (the *
9 * "Software"), to deal in the Software without restriction, including *
10 * without limitation the rights to use, copy, modify, merge, publish, *
11 * distribute, distribute with modifications, sublicense, and/or sell *
12 * copies of the Software, and to permit persons to whom the Software is *
13 * furnished to do so, subject to the following conditions: *
14 * *
15 * The above copyright notice and this permission notice shall be included *
16 * in all copies or substantial portions of the Software. *
17 * *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
24 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
25 * *
26 * Except as contained in this notice, the name(s) of the above copyright *
27 * holders shall not be used in advertising or otherwise to promote the *
28 * sale, use or other dealings in this Software without prior written *
29 * authorization. *
30 ****************************************************************************/
31
32 /****************************************************************************
33 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
34 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
35 ****************************************************************************/
36
37 /*
38 ** lib_overlay.c
39 **
40 ** The routines overlay(), copywin(), and overwrite().
41 **
42 */
43
44 #include <curses.priv.h>
45
46 MODULE_ID("$Id: lib_overlay.c,v 1.4 2023/10/17 09:52:08 nicm Exp $")
47
48 static int
overlap(const WINDOW * const src,WINDOW * const dst,int const flag)49 overlap(const WINDOW *const src, WINDOW *const dst, int const flag)
50 {
51 int rc = ERR;
52
53 T((T_CALLED("overlap(%p,%p,%d)"), (const void *) src, (void *) dst, flag));
54
55 if (src != 0 && dst != 0) {
56 int sx1, sy1, sx2, sy2;
57 int dx1, dy1, dx2, dy2;
58
59 _nc_lock_global(curses);
60
61 T(("src : begy %ld, begx %ld, maxy %ld, maxx %ld",
62 (long) src->_begy,
63 (long) src->_begx,
64 (long) src->_maxy,
65 (long) src->_maxx));
66 T(("dst : begy %ld, begx %ld, maxy %ld, maxx %ld",
67 (long) dst->_begy,
68 (long) dst->_begx,
69 (long) dst->_maxy,
70 (long) dst->_maxx));
71
72 sx1 = src->_begx;
73 sy1 = src->_begy;
74 sx2 = sx1 + src->_maxx;
75 sy2 = sy1 + src->_maxy;
76
77 dx1 = dst->_begx;
78 dy1 = dst->_begy;
79 dx2 = dx1 + dst->_maxx;
80 dy2 = dy1 + dst->_maxy;
81
82 if (dx2 >= sx1 && dx1 <= sx2 && dy2 >= sy1 && dy1 <= sy2) {
83 int sminrow = max(sy1, dy1) - sy1;
84 int smincol = max(sx1, dx1) - sx1;
85 int dminrow = max(sy1, dy1) - dy1;
86 int dmincol = max(sx1, dx1) - dx1;
87 int dmaxrow = min(sy2, dy2) - dy1;
88 int dmaxcol = min(sx2, dx2) - dx1;
89
90 rc = copywin(src, dst,
91 sminrow, smincol,
92 dminrow, dmincol,
93 dmaxrow, dmaxcol,
94 flag);
95 }
96 _nc_unlock_global(curses);
97 }
98 returnCode(rc);
99 }
100
101 /*
102 **
103 ** overlay(win1, win2)
104 **
105 **
106 ** overlay() writes the overlapping area of win1 behind win2
107 ** on win2 non-destructively.
108 **
109 **/
110
111 NCURSES_EXPORT(int)
overlay(const WINDOW * win1,WINDOW * win2)112 overlay(const WINDOW *win1, WINDOW *win2)
113 {
114 T((T_CALLED("overlay(%p,%p)"), (const void *) win1, (void *) win2));
115 returnCode(overlap(win1, win2, TRUE));
116 }
117
118 /*
119 **
120 ** overwrite(win1, win2)
121 **
122 **
123 ** overwrite() writes the overlapping area of win1 behind win2
124 ** on win2 destructively.
125 **
126 **/
127
128 NCURSES_EXPORT(int)
overwrite(const WINDOW * win1,WINDOW * win2)129 overwrite(const WINDOW *win1, WINDOW *win2)
130 {
131 T((T_CALLED("overwrite(%p,%p)"), (const void *) win1, (void *) win2));
132 returnCode(overlap(win1, win2, FALSE));
133 }
134
135 NCURSES_EXPORT(int)
copywin(const WINDOW * src,WINDOW * dst,int sminrow,int smincol,int dminrow,int dmincol,int dmaxrow,int dmaxcol,int over)136 copywin(const WINDOW *src, WINDOW *dst,
137 int sminrow, int smincol,
138 int dminrow, int dmincol,
139 int dmaxrow, int dmaxcol,
140 int over)
141 {
142 int rc = ERR;
143
144 T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"),
145 (const void *) src,
146 (void *) dst,
147 sminrow, smincol,
148 dminrow, dmincol,
149 dmaxrow, dmaxcol, over));
150
151 if (src != 0
152 && dst != 0
153 && dmaxrow >= dminrow
154 && dmaxcol >= dmincol) {
155 attr_t bk;
156 attr_t mask;
157
158 _nc_lock_global(curses);
159
160 bk = AttrOf(dst->_nc_bkgd);
161 mask = ~(attr_t) ((bk & A_COLOR) ? A_COLOR : 0);
162
163 /* make sure rectangle exists in source */
164 if ((sminrow + dmaxrow - dminrow) <= (src->_maxy + 1) &&
165 (smincol + dmaxcol - dmincol) <= (src->_maxx + 1)) {
166
167 T(("rectangle exists in source"));
168
169 /* make sure rectangle fits in destination */
170 if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) {
171 int sx, sy, dx, dy;
172 bool copied = FALSE;
173
174 T(("rectangle fits in destination"));
175
176 for (dy = dminrow, sy = sminrow;
177 dy <= dmaxrow;
178 sy++, dy++) {
179 bool touched;
180
181 if (dy < 0 || sy < 0)
182 continue;
183
184 touched = FALSE;
185 for (dx = dmincol, sx = smincol;
186 dx <= dmaxcol;
187 sx++, dx++) {
188
189 if (dx < 0 || sx < 0)
190 continue;
191 copied = TRUE;
192
193 if (over) {
194 if ((CharOf(src->_line[sy].text[sx]) != L(' ')) &&
195 (!CharEq(dst->_line[dy].text[dx],
196 src->_line[sy].text[sx]))) {
197 dst->_line[dy].text[dx] =
198 src->_line[sy].text[sx];
199 SetAttr(dst->_line[dy].text[dx],
200 ((AttrOf(src->_line[sy].text[sx]) &
201 mask) | bk));
202 touched = TRUE;
203 }
204 } else {
205 if (!CharEq(dst->_line[dy].text[dx],
206 src->_line[sy].text[sx])) {
207 dst->_line[dy].text[dx] =
208 src->_line[sy].text[sx];
209 touched = TRUE;
210 }
211 }
212 }
213 if (touched) {
214 touchline(dst, dminrow, (dmaxrow - dminrow + 1));
215 }
216 }
217 T(("finished copywin"));
218 if (copied)
219 rc = OK;
220 }
221 }
222 _nc_unlock_global(curses);
223 }
224 returnCode(rc);
225 }
226