xref: /freebsd/contrib/ncurses/ncurses/base/lib_overlay.c (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
10e3d5408SPeter Wemm /****************************************************************************
2*21817992SBaptiste Daroussin  * Copyright 2020,2023 Thomas E. Dickey                                     *
3e1865124SBaptiste Daroussin  * Copyright 1998-2013,2016 Free Software Foundation, Inc.                  *
40e3d5408SPeter Wemm  *                                                                          *
50e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
60e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
70e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
80e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
90e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
100e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
110e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
120e3d5408SPeter Wemm  *                                                                          *
130e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
140e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
150e3d5408SPeter Wemm  *                                                                          *
160e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
170e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
180e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
190e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
200e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
210e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
220e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
230e3d5408SPeter Wemm  *                                                                          *
240e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
250e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
260e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
270e3d5408SPeter Wemm  * authorization.                                                           *
280e3d5408SPeter Wemm  ****************************************************************************/
290e3d5408SPeter Wemm 
300e3d5408SPeter Wemm /****************************************************************************
310e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
320e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
330e3d5408SPeter Wemm  ****************************************************************************/
340e3d5408SPeter Wemm 
350e3d5408SPeter Wemm /*
360e3d5408SPeter Wemm **	lib_overlay.c
370e3d5408SPeter Wemm **
380e3d5408SPeter Wemm **	The routines overlay(), copywin(), and overwrite().
390e3d5408SPeter Wemm **
400e3d5408SPeter Wemm */
410e3d5408SPeter Wemm 
420e3d5408SPeter Wemm #include <curses.priv.h>
430e3d5408SPeter Wemm 
44*21817992SBaptiste Daroussin MODULE_ID("$Id: lib_overlay.c,v 1.34 2023/09/16 16:39:07 tom Exp $")
450e3d5408SPeter Wemm 
467a69bbfbSPeter Wemm static int
overlap(const WINDOW * const src,WINDOW * const dst,int const flag)47aa59d4d4SRong-En Fan overlap(const WINDOW *const src, WINDOW *const dst, int const flag)
480e3d5408SPeter Wemm {
49aa59d4d4SRong-En Fan     int rc = ERR;
500e3d5408SPeter Wemm 
5106bfebdeSXin LI     T((T_CALLED("overlap(%p,%p,%d)"), (const void *) src, (void *) dst, flag));
520e3d5408SPeter Wemm 
53aa59d4d4SRong-En Fan     if (src != 0 && dst != 0) {
54aae38d10SBaptiste Daroussin 	int sx1, sy1, sx2, sy2;
55aae38d10SBaptiste Daroussin 	int dx1, dy1, dx2, dy2;
56aae38d10SBaptiste Daroussin 
575d08fb1fSRong-En Fan 	_nc_lock_global(curses);
58aa59d4d4SRong-En Fan 
594a1a9510SRong-En Fan 	T(("src : begy %ld, begx %ld, maxy %ld, maxx %ld",
60aa59d4d4SRong-En Fan 	   (long) src->_begy,
61aa59d4d4SRong-En Fan 	   (long) src->_begx,
62aa59d4d4SRong-En Fan 	   (long) src->_maxy,
63aa59d4d4SRong-En Fan 	   (long) src->_maxx));
644a1a9510SRong-En Fan 	T(("dst : begy %ld, begx %ld, maxy %ld, maxx %ld",
65aa59d4d4SRong-En Fan 	   (long) dst->_begy,
66aa59d4d4SRong-En Fan 	   (long) dst->_begx,
67aa59d4d4SRong-En Fan 	   (long) dst->_maxy,
68aa59d4d4SRong-En Fan 	   (long) dst->_maxx));
690e3d5408SPeter Wemm 
70aa59d4d4SRong-En Fan 	sx1 = src->_begx;
71aa59d4d4SRong-En Fan 	sy1 = src->_begy;
72aa59d4d4SRong-En Fan 	sx2 = sx1 + src->_maxx;
73aa59d4d4SRong-En Fan 	sy2 = sy1 + src->_maxy;
740e3d5408SPeter Wemm 
75aa59d4d4SRong-En Fan 	dx1 = dst->_begx;
76aa59d4d4SRong-En Fan 	dy1 = dst->_begy;
77aa59d4d4SRong-En Fan 	dx2 = dx1 + dst->_maxx;
78aa59d4d4SRong-En Fan 	dy2 = dy1 + dst->_maxy;
794a1a9510SRong-En Fan 
80aa59d4d4SRong-En Fan 	if (dx2 >= sx1 && dx1 <= sx2 && dy2 >= sy1 && dy1 <= sy2) {
81*21817992SBaptiste Daroussin 	    int sminrow = Max(sy1, dy1) - sy1;
82*21817992SBaptiste Daroussin 	    int smincol = Max(sx1, dx1) - sx1;
83*21817992SBaptiste Daroussin 	    int dminrow = Max(sy1, dy1) - dy1;
84*21817992SBaptiste Daroussin 	    int dmincol = Max(sx1, dx1) - dx1;
85*21817992SBaptiste Daroussin 	    int dmaxrow = Min(sy2, dy2) - dy1;
86*21817992SBaptiste Daroussin 	    int dmaxcol = Min(sx2, dx2) - dx1;
874a1a9510SRong-En Fan 
88aa59d4d4SRong-En Fan 	    rc = copywin(src, dst,
894a1a9510SRong-En Fan 			 sminrow, smincol,
904a1a9510SRong-En Fan 			 dminrow, dmincol,
914a1a9510SRong-En Fan 			 dmaxrow, dmaxcol,
92aa59d4d4SRong-En Fan 			 flag);
930e3d5408SPeter Wemm 	}
945d08fb1fSRong-En Fan 	_nc_unlock_global(curses);
954a1a9510SRong-En Fan     }
96aa59d4d4SRong-En Fan     returnCode(rc);
974a1a9510SRong-En Fan }
980e3d5408SPeter Wemm 
990e3d5408SPeter Wemm /*
1000e3d5408SPeter Wemm **
1010e3d5408SPeter Wemm **	overlay(win1, win2)
1020e3d5408SPeter Wemm **
1030e3d5408SPeter Wemm **
1040e3d5408SPeter Wemm **	overlay() writes the overlapping area of win1 behind win2
1050e3d5408SPeter Wemm **	on win2 non-destructively.
1060e3d5408SPeter Wemm **
1070e3d5408SPeter Wemm **/
1080e3d5408SPeter Wemm 
1097a69bbfbSPeter Wemm NCURSES_EXPORT(int)
overlay(const WINDOW * win1,WINDOW * win2)1107a69bbfbSPeter Wemm overlay(const WINDOW *win1, WINDOW *win2)
1110e3d5408SPeter Wemm {
11206bfebdeSXin LI     T((T_CALLED("overlay(%p,%p)"), (const void *) win1, (void *) win2));
1130e3d5408SPeter Wemm     returnCode(overlap(win1, win2, TRUE));
1140e3d5408SPeter Wemm }
1150e3d5408SPeter Wemm 
1160e3d5408SPeter Wemm /*
1170e3d5408SPeter Wemm **
1180e3d5408SPeter Wemm **	overwrite(win1, win2)
1190e3d5408SPeter Wemm **
1200e3d5408SPeter Wemm **
1210e3d5408SPeter Wemm **	overwrite() writes the overlapping area of win1 behind win2
1220e3d5408SPeter Wemm **	on win2 destructively.
1230e3d5408SPeter Wemm **
1240e3d5408SPeter Wemm **/
1250e3d5408SPeter Wemm 
1267a69bbfbSPeter Wemm NCURSES_EXPORT(int)
overwrite(const WINDOW * win1,WINDOW * win2)1277a69bbfbSPeter Wemm overwrite(const WINDOW *win1, WINDOW *win2)
1280e3d5408SPeter Wemm {
12906bfebdeSXin LI     T((T_CALLED("overwrite(%p,%p)"), (const void *) win1, (void *) win2));
1300e3d5408SPeter Wemm     returnCode(overlap(win1, win2, FALSE));
1310e3d5408SPeter Wemm }
1320e3d5408SPeter Wemm 
1337a69bbfbSPeter Wemm NCURSES_EXPORT(int)
copywin(const WINDOW * src,WINDOW * dst,int sminrow,int smincol,int dminrow,int dmincol,int dmaxrow,int dmaxcol,int over)1344a1a9510SRong-En Fan copywin(const WINDOW *src, WINDOW *dst,
1350e3d5408SPeter Wemm 	int sminrow, int smincol,
1364a1a9510SRong-En Fan 	int dminrow, int dmincol,
1374a1a9510SRong-En Fan 	int dmaxrow, int dmaxcol,
1380e3d5408SPeter Wemm 	int over)
1390e3d5408SPeter Wemm {
140aa59d4d4SRong-En Fan     int rc = ERR;
1410e3d5408SPeter Wemm 
1420e3d5408SPeter Wemm     T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"),
14306bfebdeSXin LI        (const void *) src,
14406bfebdeSXin LI        (void *) dst,
14506bfebdeSXin LI        sminrow, smincol,
14606bfebdeSXin LI        dminrow, dmincol,
14706bfebdeSXin LI        dmaxrow, dmaxcol, over));
1480e3d5408SPeter Wemm 
14973f0a83dSXin LI     if (src != 0
15073f0a83dSXin LI 	&& dst != 0
15173f0a83dSXin LI 	&& dmaxrow >= dminrow
15273f0a83dSXin LI 	&& dmaxcol >= dmincol) {
153aae38d10SBaptiste Daroussin 	attr_t bk;
154aae38d10SBaptiste Daroussin 	attr_t mask;
155aae38d10SBaptiste Daroussin 
1565d08fb1fSRong-En Fan 	_nc_lock_global(curses);
1570e3d5408SPeter Wemm 
1585ca44d1cSRong-En Fan 	bk = AttrOf(dst->_nc_bkgd);
1595ca44d1cSRong-En Fan 	mask = ~(attr_t) ((bk & A_COLOR) ? A_COLOR : 0);
1605ca44d1cSRong-En Fan 
1610e3d5408SPeter Wemm 	/* make sure rectangle exists in source */
162aa59d4d4SRong-En Fan 	if ((sminrow + dmaxrow - dminrow) <= (src->_maxy + 1) &&
163aa59d4d4SRong-En Fan 	    (smincol + dmaxcol - dmincol) <= (src->_maxx + 1)) {
1640e3d5408SPeter Wemm 
1650e3d5408SPeter Wemm 	    T(("rectangle exists in source"));
1660e3d5408SPeter Wemm 
1670e3d5408SPeter Wemm 	    /* make sure rectangle fits in destination */
168aa59d4d4SRong-En Fan 	    if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) {
169aae38d10SBaptiste Daroussin 		int sx, sy, dx, dy;
170aae38d10SBaptiste Daroussin 		bool copied = FALSE;
1710e3d5408SPeter Wemm 
1720e3d5408SPeter Wemm 		T(("rectangle fits in destination"));
1730e3d5408SPeter Wemm 
174aa59d4d4SRong-En Fan 		for (dy = dminrow, sy = sminrow;
175aa59d4d4SRong-En Fan 		     dy <= dmaxrow;
176aa59d4d4SRong-En Fan 		     sy++, dy++) {
177aae38d10SBaptiste Daroussin 		    bool touched;
178aa59d4d4SRong-En Fan 
17973f0a83dSXin LI 		    if (dy < 0 || sy < 0)
18073f0a83dSXin LI 			continue;
18173f0a83dSXin LI 
1820e3d5408SPeter Wemm 		    touched = FALSE;
183aa59d4d4SRong-En Fan 		    for (dx = dmincol, sx = smincol;
184aa59d4d4SRong-En Fan 			 dx <= dmaxcol;
185aa59d4d4SRong-En Fan 			 sx++, dx++) {
18673f0a83dSXin LI 
18773f0a83dSXin LI 			if (dx < 0 || sx < 0)
18873f0a83dSXin LI 			    continue;
18973f0a83dSXin LI 			copied = TRUE;
19073f0a83dSXin LI 
1917a69bbfbSPeter Wemm 			if (over) {
19239f2269fSPeter Wemm 			    if ((CharOf(src->_line[sy].text[sx]) != L(' ')) &&
193aa59d4d4SRong-En Fan 				(!CharEq(dst->_line[dy].text[dx],
194aa59d4d4SRong-En Fan 					 src->_line[sy].text[sx]))) {
195aa59d4d4SRong-En Fan 				dst->_line[dy].text[dx] =
196aa59d4d4SRong-En Fan 				    src->_line[sy].text[sx];
19739f2269fSPeter Wemm 				SetAttr(dst->_line[dy].text[dx],
198aa59d4d4SRong-En Fan 					((AttrOf(src->_line[sy].text[sx]) &
199aa59d4d4SRong-En Fan 					  mask) | bk));
2000e3d5408SPeter Wemm 				touched = TRUE;
2010e3d5408SPeter Wemm 			    }
2027a69bbfbSPeter Wemm 			} else {
203aa59d4d4SRong-En Fan 			    if (!CharEq(dst->_line[dy].text[dx],
204aa59d4d4SRong-En Fan 					src->_line[sy].text[sx])) {
205aa59d4d4SRong-En Fan 				dst->_line[dy].text[dx] =
206aa59d4d4SRong-En Fan 				    src->_line[sy].text[sx];
2070e3d5408SPeter Wemm 				touched = TRUE;
2080e3d5408SPeter Wemm 			    }
2090e3d5408SPeter Wemm 			}
2100e3d5408SPeter Wemm 		    }
2117a69bbfbSPeter Wemm 		    if (touched) {
2124a1a9510SRong-En Fan 			touchline(dst, dminrow, (dmaxrow - dminrow + 1));
2130e3d5408SPeter Wemm 		    }
2140e3d5408SPeter Wemm 		}
2150e3d5408SPeter Wemm 		T(("finished copywin"));
21673f0a83dSXin LI 		if (copied)
217aa59d4d4SRong-En Fan 		    rc = OK;
218aa59d4d4SRong-En Fan 	    }
219aa59d4d4SRong-En Fan 	}
2205d08fb1fSRong-En Fan 	_nc_unlock_global(curses);
221aa59d4d4SRong-En Fan     }
222aa59d4d4SRong-En Fan     returnCode(rc);
2230e3d5408SPeter Wemm }
224