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