xref: /openbsd/lib/libcurses/base/lib_overlay.c (revision c7ef0cfc)
1*c7ef0cfcSnicm /* $OpenBSD: lib_overlay.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */
292dd1ec0Smillert 
392dd1ec0Smillert /****************************************************************************
4*c7ef0cfcSnicm  * Copyright 2020 Thomas E. Dickey                                          *
5*c7ef0cfcSnicm  * Copyright 1998-2013,2016 Free Software Foundation, Inc.                  *
692dd1ec0Smillert  *                                                                          *
792dd1ec0Smillert  * Permission is hereby granted, free of charge, to any person obtaining a  *
892dd1ec0Smillert  * copy of this software and associated documentation files (the            *
992dd1ec0Smillert  * "Software"), to deal in the Software without restriction, including      *
1092dd1ec0Smillert  * without limitation the rights to use, copy, modify, merge, publish,      *
1192dd1ec0Smillert  * distribute, distribute with modifications, sublicense, and/or sell       *
1292dd1ec0Smillert  * copies of the Software, and to permit persons to whom the Software is    *
1392dd1ec0Smillert  * furnished to do so, subject to the following conditions:                 *
1492dd1ec0Smillert  *                                                                          *
1592dd1ec0Smillert  * The above copyright notice and this permission notice shall be included  *
1692dd1ec0Smillert  * in all copies or substantial portions of the Software.                   *
1792dd1ec0Smillert  *                                                                          *
1892dd1ec0Smillert  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1992dd1ec0Smillert  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
2092dd1ec0Smillert  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
2192dd1ec0Smillert  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
2292dd1ec0Smillert  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2392dd1ec0Smillert  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2492dd1ec0Smillert  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2592dd1ec0Smillert  *                                                                          *
2692dd1ec0Smillert  * Except as contained in this notice, the name(s) of the above copyright   *
2792dd1ec0Smillert  * holders shall not be used in advertising or otherwise to promote the     *
2892dd1ec0Smillert  * sale, use or other dealings in this Software without prior written       *
2992dd1ec0Smillert  * authorization.                                                           *
3092dd1ec0Smillert  ****************************************************************************/
3192dd1ec0Smillert 
3292dd1ec0Smillert /****************************************************************************
3392dd1ec0Smillert  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
3492dd1ec0Smillert  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
3592dd1ec0Smillert  ****************************************************************************/
3692dd1ec0Smillert 
3792dd1ec0Smillert /*
3892dd1ec0Smillert **	lib_overlay.c
3992dd1ec0Smillert **
4092dd1ec0Smillert **	The routines overlay(), copywin(), and overwrite().
4192dd1ec0Smillert **
4292dd1ec0Smillert */
4392dd1ec0Smillert 
4492dd1ec0Smillert #include <curses.priv.h>
4592dd1ec0Smillert 
46*c7ef0cfcSnicm MODULE_ID("$Id: lib_overlay.c,v 1.4 2023/10/17 09:52:08 nicm Exp $")
4792dd1ec0Smillert 
4884af20ceSmillert static int
overlap(const WINDOW * const src,WINDOW * const dst,int const flag)4981d8c4e1Snicm overlap(const WINDOW *const src, WINDOW *const dst, int const flag)
5092dd1ec0Smillert {
5181d8c4e1Snicm     int rc = ERR;
5292dd1ec0Smillert 
53*c7ef0cfcSnicm     T((T_CALLED("overlap(%p,%p,%d)"), (const void *) src, (void *) dst, flag));
5492dd1ec0Smillert 
5581d8c4e1Snicm     if (src != 0 && dst != 0) {
56*c7ef0cfcSnicm 	int sx1, sy1, sx2, sy2;
57*c7ef0cfcSnicm 	int dx1, dy1, dx2, dy2;
58*c7ef0cfcSnicm 
5981d8c4e1Snicm 	_nc_lock_global(curses);
6092dd1ec0Smillert 
6181d8c4e1Snicm 	T(("src : begy %ld, begx %ld, maxy %ld, maxx %ld",
6281d8c4e1Snicm 	   (long) src->_begy,
6381d8c4e1Snicm 	   (long) src->_begx,
6481d8c4e1Snicm 	   (long) src->_maxy,
6581d8c4e1Snicm 	   (long) src->_maxx));
6681d8c4e1Snicm 	T(("dst : begy %ld, begx %ld, maxy %ld, maxx %ld",
6781d8c4e1Snicm 	   (long) dst->_begy,
6881d8c4e1Snicm 	   (long) dst->_begx,
6981d8c4e1Snicm 	   (long) dst->_maxy,
7081d8c4e1Snicm 	   (long) dst->_maxx));
7192dd1ec0Smillert 
7281d8c4e1Snicm 	sx1 = src->_begx;
7381d8c4e1Snicm 	sy1 = src->_begy;
7481d8c4e1Snicm 	sx2 = sx1 + src->_maxx;
7581d8c4e1Snicm 	sy2 = sy1 + src->_maxy;
7681d8c4e1Snicm 
7781d8c4e1Snicm 	dx1 = dst->_begx;
7881d8c4e1Snicm 	dy1 = dst->_begy;
7981d8c4e1Snicm 	dx2 = dx1 + dst->_maxx;
8081d8c4e1Snicm 	dy2 = dy1 + dst->_maxy;
8181d8c4e1Snicm 
8281d8c4e1Snicm 	if (dx2 >= sx1 && dx1 <= sx2 && dy2 >= sy1 && dy1 <= sy2) {
83*c7ef0cfcSnicm 	    int sminrow = max(sy1, dy1) - sy1;
84*c7ef0cfcSnicm 	    int smincol = max(sx1, dx1) - sx1;
85*c7ef0cfcSnicm 	    int dminrow = max(sy1, dy1) - dy1;
86*c7ef0cfcSnicm 	    int dmincol = max(sx1, dx1) - dx1;
87*c7ef0cfcSnicm 	    int dmaxrow = min(sy2, dy2) - dy1;
88*c7ef0cfcSnicm 	    int dmaxcol = min(sx2, dx2) - dx1;
8981d8c4e1Snicm 
9081d8c4e1Snicm 	    rc = copywin(src, dst,
9181d8c4e1Snicm 			 sminrow, smincol,
9281d8c4e1Snicm 			 dminrow, dmincol,
9381d8c4e1Snicm 			 dmaxrow, dmaxcol,
9481d8c4e1Snicm 			 flag);
9581d8c4e1Snicm 	}
9681d8c4e1Snicm 	_nc_unlock_global(curses);
9781d8c4e1Snicm     }
9881d8c4e1Snicm     returnCode(rc);
9992dd1ec0Smillert }
10092dd1ec0Smillert 
10192dd1ec0Smillert /*
10292dd1ec0Smillert **
10392dd1ec0Smillert **	overlay(win1, win2)
10492dd1ec0Smillert **
10592dd1ec0Smillert **
10692dd1ec0Smillert **	overlay() writes the overlapping area of win1 behind win2
10792dd1ec0Smillert **	on win2 non-destructively.
10892dd1ec0Smillert **
10992dd1ec0Smillert **/
11092dd1ec0Smillert 
11184af20ceSmillert NCURSES_EXPORT(int)
overlay(const WINDOW * win1,WINDOW * win2)11284af20ceSmillert overlay(const WINDOW *win1, WINDOW *win2)
11392dd1ec0Smillert {
114*c7ef0cfcSnicm     T((T_CALLED("overlay(%p,%p)"), (const void *) win1, (void *) win2));
11592dd1ec0Smillert     returnCode(overlap(win1, win2, TRUE));
11692dd1ec0Smillert }
11792dd1ec0Smillert 
11892dd1ec0Smillert /*
11992dd1ec0Smillert **
12092dd1ec0Smillert **	overwrite(win1, win2)
12192dd1ec0Smillert **
12292dd1ec0Smillert **
12392dd1ec0Smillert **	overwrite() writes the overlapping area of win1 behind win2
12492dd1ec0Smillert **	on win2 destructively.
12592dd1ec0Smillert **
12692dd1ec0Smillert **/
12792dd1ec0Smillert 
12884af20ceSmillert NCURSES_EXPORT(int)
overwrite(const WINDOW * win1,WINDOW * win2)12984af20ceSmillert overwrite(const WINDOW *win1, WINDOW *win2)
13092dd1ec0Smillert {
131*c7ef0cfcSnicm     T((T_CALLED("overwrite(%p,%p)"), (const void *) win1, (void *) win2));
13292dd1ec0Smillert     returnCode(overlap(win1, win2, FALSE));
13392dd1ec0Smillert }
13492dd1ec0Smillert 
13584af20ceSmillert NCURSES_EXPORT(int)
copywin(const WINDOW * src,WINDOW * dst,int sminrow,int smincol,int dminrow,int dmincol,int dmaxrow,int dmaxcol,int over)13681d8c4e1Snicm copywin(const WINDOW *src, WINDOW *dst,
13792dd1ec0Smillert 	int sminrow, int smincol,
13881d8c4e1Snicm 	int dminrow, int dmincol,
13981d8c4e1Snicm 	int dmaxrow, int dmaxcol,
14092dd1ec0Smillert 	int over)
14192dd1ec0Smillert {
14281d8c4e1Snicm     int rc = ERR;
143*c7ef0cfcSnicm 
144*c7ef0cfcSnicm     T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"),
145*c7ef0cfcSnicm        (const void *) src,
146*c7ef0cfcSnicm        (void *) dst,
147*c7ef0cfcSnicm        sminrow, smincol,
148*c7ef0cfcSnicm        dminrow, dmincol,
149*c7ef0cfcSnicm        dmaxrow, dmaxcol, over));
150*c7ef0cfcSnicm 
151*c7ef0cfcSnicm     if (src != 0
152*c7ef0cfcSnicm 	&& dst != 0
153*c7ef0cfcSnicm 	&& dmaxrow >= dminrow
154*c7ef0cfcSnicm 	&& dmaxcol >= dmincol) {
15581d8c4e1Snicm 	attr_t bk;
15681d8c4e1Snicm 	attr_t mask;
15792dd1ec0Smillert 
15881d8c4e1Snicm 	_nc_lock_global(curses);
15981d8c4e1Snicm 
16081d8c4e1Snicm 	bk = AttrOf(dst->_nc_bkgd);
16181d8c4e1Snicm 	mask = ~(attr_t) ((bk & A_COLOR) ? A_COLOR : 0);
16292dd1ec0Smillert 
16392dd1ec0Smillert 	/* make sure rectangle exists in source */
16481d8c4e1Snicm 	if ((sminrow + dmaxrow - dminrow) <= (src->_maxy + 1) &&
16581d8c4e1Snicm 	    (smincol + dmaxcol - dmincol) <= (src->_maxx + 1)) {
16692dd1ec0Smillert 
16792dd1ec0Smillert 	    T(("rectangle exists in source"));
16892dd1ec0Smillert 
16992dd1ec0Smillert 	    /* make sure rectangle fits in destination */
17081d8c4e1Snicm 	    if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) {
171*c7ef0cfcSnicm 		int sx, sy, dx, dy;
172*c7ef0cfcSnicm 		bool copied = FALSE;
17392dd1ec0Smillert 
17492dd1ec0Smillert 		T(("rectangle fits in destination"));
17592dd1ec0Smillert 
17681d8c4e1Snicm 		for (dy = dminrow, sy = sminrow;
17781d8c4e1Snicm 		     dy <= dmaxrow;
17881d8c4e1Snicm 		     sy++, dy++) {
179*c7ef0cfcSnicm 		    bool touched;
180*c7ef0cfcSnicm 
181*c7ef0cfcSnicm 		    if (dy < 0 || sy < 0)
182*c7ef0cfcSnicm 			continue;
18381d8c4e1Snicm 
18492dd1ec0Smillert 		    touched = FALSE;
18581d8c4e1Snicm 		    for (dx = dmincol, sx = smincol;
18681d8c4e1Snicm 			 dx <= dmaxcol;
18781d8c4e1Snicm 			 sx++, dx++) {
188*c7ef0cfcSnicm 
189*c7ef0cfcSnicm 			if (dx < 0 || sx < 0)
190*c7ef0cfcSnicm 			    continue;
191*c7ef0cfcSnicm 			copied = TRUE;
192*c7ef0cfcSnicm 
19384af20ceSmillert 			if (over) {
19481d8c4e1Snicm 			    if ((CharOf(src->_line[sy].text[sx]) != L(' ')) &&
19581d8c4e1Snicm 				(!CharEq(dst->_line[dy].text[dx],
19681d8c4e1Snicm 					 src->_line[sy].text[sx]))) {
19792dd1ec0Smillert 				dst->_line[dy].text[dx] =
19881d8c4e1Snicm 				    src->_line[sy].text[sx];
19981d8c4e1Snicm 				SetAttr(dst->_line[dy].text[dx],
20081d8c4e1Snicm 					((AttrOf(src->_line[sy].text[sx]) &
20181d8c4e1Snicm 					  mask) | bk));
20292dd1ec0Smillert 				touched = TRUE;
20392dd1ec0Smillert 			    }
20484af20ceSmillert 			} else {
20581d8c4e1Snicm 			    if (!CharEq(dst->_line[dy].text[dx],
20681d8c4e1Snicm 					src->_line[sy].text[sx])) {
20781d8c4e1Snicm 				dst->_line[dy].text[dx] =
20881d8c4e1Snicm 				    src->_line[sy].text[sx];
20992dd1ec0Smillert 				touched = TRUE;
21092dd1ec0Smillert 			    }
21192dd1ec0Smillert 			}
21292dd1ec0Smillert 		    }
21384af20ceSmillert 		    if (touched) {
21481d8c4e1Snicm 			touchline(dst, dminrow, (dmaxrow - dminrow + 1));
21592dd1ec0Smillert 		    }
21692dd1ec0Smillert 		}
21792dd1ec0Smillert 		T(("finished copywin"));
218*c7ef0cfcSnicm 		if (copied)
21981d8c4e1Snicm 		    rc = OK;
22081d8c4e1Snicm 	    }
22181d8c4e1Snicm 	}
22281d8c4e1Snicm 	_nc_unlock_global(curses);
22381d8c4e1Snicm     }
22481d8c4e1Snicm     returnCode(rc);
22592dd1ec0Smillert }
226