xref: /netbsd-src/lib/libcurses/background.c (revision 6348e3f32a4431b45d07e1da16fd7b12725a45e7)
1*6348e3f3Sblymn /*	$NetBSD: background.c,v 1.34 2024/12/23 02:58:03 blymn Exp $	*/
292d0751bSjdc 
392d0751bSjdc /*-
492d0751bSjdc  * Copyright (c) 2000 The NetBSD Foundation, Inc.
592d0751bSjdc  * All rights reserved.
692d0751bSjdc  *
792d0751bSjdc  * This code is derived from software contributed to The NetBSD Foundation
892d0751bSjdc  * by Julian Coleman.
992d0751bSjdc  *
1092d0751bSjdc  * Redistribution and use in source and binary forms, with or without
1192d0751bSjdc  * modification, are permitted provided that the following conditions
1292d0751bSjdc  * are met:
1392d0751bSjdc  * 1. Redistributions of source code must retain the above copyright
1492d0751bSjdc  *    notice, this list of conditions and the following disclaimer.
1592d0751bSjdc  * 2. Redistributions in binary form must reproduce the above copyright
1692d0751bSjdc  *    notice, this list of conditions and the following disclaimer in the
1792d0751bSjdc  *    documentation and/or other materials provided with the distribution.
1892d0751bSjdc  *
1992d0751bSjdc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2092d0751bSjdc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2192d0751bSjdc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2292d0751bSjdc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2392d0751bSjdc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2492d0751bSjdc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2592d0751bSjdc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2692d0751bSjdc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2792d0751bSjdc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2892d0751bSjdc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2992d0751bSjdc  * POSSIBILITY OF SUCH DAMAGE.
3092d0751bSjdc  */
3192d0751bSjdc 
3266cab71cSblymn #include <sys/cdefs.h>
3366cab71cSblymn #ifndef lint
34*6348e3f3Sblymn __RCSID("$NetBSD: background.c,v 1.34 2024/12/23 02:58:03 blymn Exp $");
3566cab71cSblymn #endif				/* not lint */
3666cab71cSblymn 
37e124de36Sblymn #include <stdlib.h>
3892d0751bSjdc #include "curses.h"
3992d0751bSjdc #include "curses_private.h"
4092d0751bSjdc 
4192d0751bSjdc /*
42032680bbSjdc  * bkgdset
43032680bbSjdc  *	Set new background attributes on stdscr.
44032680bbSjdc  */
45032680bbSjdc void
46032680bbSjdc bkgdset(chtype ch)
47032680bbSjdc {
48032680bbSjdc 	wbkgdset(stdscr, ch);
49032680bbSjdc }
50032680bbSjdc 
51032680bbSjdc /*
52032680bbSjdc  * bkgd --
5314d02454Suwe  *	Set new background attributes on stdscr and apply them to its
5414d02454Suwe  *	contents.
55032680bbSjdc  */
56032680bbSjdc int
57032680bbSjdc bkgd(chtype ch)
58032680bbSjdc {
59032680bbSjdc 	return(wbkgd(stdscr, ch));
60032680bbSjdc }
61032680bbSjdc 
62032680bbSjdc /*
6392d0751bSjdc  * wbkgdset
6414d02454Suwe  *	Set new background attributes on the specified window.
6592d0751bSjdc  */
6692d0751bSjdc void
67aaf74682Sblymn wbkgdset(WINDOW *win, chtype ch)
6892d0751bSjdc {
691f221324Sjdc 	__CTRACE(__CTRACE_ATTR, "wbkgdset: (%p), '%s', %08x\n",
703f33c7bdSuwe 	    win, unctrl(ch & __CHARTEXT), ch & __ATTRIBUTES);
714eb3ef3dSjdc 
72*6348e3f3Sblymn 	if (__predict_false(win == NULL))
73*6348e3f3Sblymn 		return;
74*6348e3f3Sblymn 
754eb3ef3dSjdc 	/* Background character. */
764eb3ef3dSjdc 	if (ch & __CHARTEXT)
774eb3ef3dSjdc 		win->bch = (wchar_t) ch & __CHARTEXT;
784eb3ef3dSjdc 
794eb3ef3dSjdc 	/* Background attributes (check colour). */
804eb3ef3dSjdc 	if (__using_color && !(ch & __COLOR))
814eb3ef3dSjdc 		ch |= __default_color;
824eb3ef3dSjdc 	win->battr = (attr_t) ch & __ATTRIBUTES;
8392d0751bSjdc }
8492d0751bSjdc 
8592d0751bSjdc /*
8692d0751bSjdc  * wbkgd --
8714d02454Suwe  *	Set new background attributes on the specified window and
8814d02454Suwe  *	apply them to its contents.
8992d0751bSjdc  */
9092d0751bSjdc int
91aaf74682Sblymn wbkgd(WINDOW *win, chtype ch)
9292d0751bSjdc {
9331355762Sjdc 	int y, x;
9431355762Sjdc 
951f221324Sjdc 	__CTRACE(__CTRACE_ATTR, "wbkgd: (%p), '%s', %08x\n",
963f33c7bdSuwe 	    win, unctrl(ch & __CHARTEXT), ch & __ATTRIBUTES);
97*6348e3f3Sblymn 
98*6348e3f3Sblymn 	if (__predict_false(win == NULL))
99*6348e3f3Sblymn 		return ERR;
100*6348e3f3Sblymn 
10192d0751bSjdc 	wbkgdset(win, ch);
102ee4af76dSuwe 
103ce63d7aaSuwe 	for (y = 0; y < win->maxy; y++) {
10431355762Sjdc 		for (x = 0; x < win->maxx; x++) {
105ce63d7aaSuwe 			__LDATA *cp = &win->alines[y]->line[x];
106ce63d7aaSuwe 
107ce63d7aaSuwe 			/* Update/switch background characters */
108a7d2c216Sblymn 			if (cp->cflags & CA_BACKGROUND)
109ce63d7aaSuwe 				cp->ch = win->bch;
110ce63d7aaSuwe 
111ce63d7aaSuwe 			/* Update/merge attributes */
112ce63d7aaSuwe 			cp->attr = win->battr | (cp->attr & __ALTCHARSET);
113fe324c36Sjdc #ifdef HAVE_WCHAR
114f1942931Sblymn 			cp->wcols = 1;
115fe324c36Sjdc #endif
11631355762Sjdc 		}
117ce63d7aaSuwe 	}
118301bf8ccSblymn 	__touchwin(win, 1);
119ce63d7aaSuwe 	return OK;
12092d0751bSjdc }
12192d0751bSjdc 
12292d0751bSjdc /*
12392d0751bSjdc  * getbkgd --
12492d0751bSjdc  *	Get current background attributes.
12592d0751bSjdc  */
12692d0751bSjdc chtype
127aaf74682Sblymn getbkgd(WINDOW *win)
12892d0751bSjdc {
1294eb3ef3dSjdc 	attr_t	battr;
1304eb3ef3dSjdc 
131*6348e3f3Sblymn 	if (__predict_false(win == NULL))
132*6348e3f3Sblymn 		return ERR;
133*6348e3f3Sblymn 
1344eb3ef3dSjdc 	/* Background attributes (check colour). */
1354eb3ef3dSjdc 	battr = win->battr & A_ATTRIBUTES;
1364eb3ef3dSjdc 	if (__using_color && ((battr & __COLOR) == __default_color))
13776bb9929Suwe 		battr &= ~__COLOR;
1384eb3ef3dSjdc 
1394eb3ef3dSjdc 	return ((chtype) ((win->bch & A_CHARTEXT) | battr));
14092d0751bSjdc }
141e124de36Sblymn 
142e124de36Sblymn 
143e124de36Sblymn #ifdef HAVE_WCHAR
1445fc07779Suwe 
1455fc07779Suwe void
1465fc07779Suwe bkgrndset(const cchar_t *wch)
1475fc07779Suwe {
148e124de36Sblymn 	wbkgrndset(stdscr, wch);
149e124de36Sblymn }
150e124de36Sblymn 
1515fc07779Suwe 
1525fc07779Suwe int
1530b616789Suwe bkgrnd(const cchar_t *wch)
154e124de36Sblymn {
1550b616789Suwe 	return wbkgrnd(stdscr, wch);
156e124de36Sblymn }
157e124de36Sblymn 
1585fc07779Suwe 
1595fc07779Suwe int
1600b616789Suwe getbkgrnd(cchar_t *wch)
161e124de36Sblymn {
1620b616789Suwe 	return wgetbkgrnd(stdscr, wch);
163e124de36Sblymn }
164e124de36Sblymn 
1655fc07779Suwe 
1665fc07779Suwe void
1675fc07779Suwe wbkgrndset(WINDOW *win, const cchar_t *wch)
168e124de36Sblymn {
169e124de36Sblymn 	attr_t battr;
170e124de36Sblymn 	nschar_t *np, *tnp;
17188123910Sblymn 	int i, wy, wx;
17288123910Sblymn 	__LDATA obkgrnd, nbkgrnd;
17388123910Sblymn 	__LINE *wlp;
174e124de36Sblymn 
175e124de36Sblymn 	__CTRACE(__CTRACE_ATTR, "wbkgrndset: (%p), '%s', %x\n",
176070937beSblymn 	    win, (const char *)wunctrl(wch), wch->attributes);
177e124de36Sblymn 
178*6348e3f3Sblymn 	if (__predict_false(win == NULL))
179*6348e3f3Sblymn 		return;
180*6348e3f3Sblymn 
181e124de36Sblymn 	/* ignore multi-column characters */
182e124de36Sblymn 	if (!wch->elements || wcwidth(wch->vals[0]) > 1)
183e124de36Sblymn 		return;
184e124de36Sblymn 
18588123910Sblymn 	/* get a copy of the old background, we will need it. */
18688123910Sblymn 	obkgrnd.ch = win->bch;
18788123910Sblymn 	obkgrnd.attr = win->battr;
188ee6c5161Sblymn 	obkgrnd.cflags = CA_BACKGROUND;
18988123910Sblymn 	obkgrnd.wcols = win->wcols;
19088123910Sblymn 	obkgrnd.nsp = NULL;
19188123910Sblymn 	_cursesi_copy_nsp(win->bnsp, &obkgrnd);
19288123910Sblymn 
193e124de36Sblymn 	/* Background character. */
194e124de36Sblymn 	tnp = np = win->bnsp;
195e124de36Sblymn 	if (wcwidth( wch->vals[0]))
196e124de36Sblymn 		win->bch = wch->vals[0];
197e124de36Sblymn 	else {
198e124de36Sblymn 		if (!np) {
1998a48cf66Schristos 			np = malloc(sizeof(nschar_t));
200e124de36Sblymn 			if (!np)
201e124de36Sblymn 				return;
202e124de36Sblymn 			np->next = NULL;
203e124de36Sblymn 			win->bnsp = np;
204e124de36Sblymn 		}
205e124de36Sblymn 		np->ch = wch->vals[0];
206e124de36Sblymn 		tnp = np;
207e124de36Sblymn 		np = np->next;
208e124de36Sblymn 	}
209e124de36Sblymn 	/* add non-spacing characters */
210e124de36Sblymn 	if (wch->elements > 1) {
211e124de36Sblymn 		for (i = 1; i < wch->elements; i++) {
212e124de36Sblymn 			if ( !np ) {
2138a48cf66Schristos 				np = malloc(sizeof(nschar_t));
214e124de36Sblymn 				if (!np)
215e124de36Sblymn 					return;
216e124de36Sblymn 				np->next = NULL;
217e124de36Sblymn 				if (tnp)
218e124de36Sblymn 					tnp->next = np;
219e124de36Sblymn 				else
220e124de36Sblymn 					win->bnsp = np;
221e124de36Sblymn 			}
222e124de36Sblymn 			np->ch = wch->vals[i];
223e124de36Sblymn 			tnp = np;
224e124de36Sblymn 			np = np->next;
225e124de36Sblymn 		}
226e124de36Sblymn 	}
227e124de36Sblymn 	/* clear the old non-spacing characters */
22888123910Sblymn 	__cursesi_free_nsp(np);
229e124de36Sblymn 
230e124de36Sblymn 	/* Background attributes (check colour). */
231e124de36Sblymn 	battr = wch->attributes & WA_ATTRIBUTES;
232e124de36Sblymn 	if (__using_color && !( battr & __COLOR))
233e124de36Sblymn 		battr |= __default_color;
234e124de36Sblymn 	win->battr = battr;
235f1942931Sblymn 	win->wcols = 1;
23688123910Sblymn 
237a7d2c216Sblymn 	nbkgrnd.ch = win->bch;
238a7d2c216Sblymn 	nbkgrnd.attr = win->battr;
239ee6c5161Sblymn 	nbkgrnd.cflags = CA_BACKGROUND;
240a7d2c216Sblymn 	nbkgrnd.wcols = win->wcols;
241a7d2c216Sblymn 	nbkgrnd.nsp = NULL;
242a7d2c216Sblymn 	_cursesi_copy_nsp(win->bnsp, &nbkgrnd);
243a7d2c216Sblymn 
244a7d2c216Sblymn 	/* if the background is already this char then skip updating */
245a7d2c216Sblymn 	if (_cursesi_celleq(&obkgrnd, &nbkgrnd))
246a7d2c216Sblymn 		return;
247a7d2c216Sblymn 
24888123910Sblymn 	/*
24988123910Sblymn 	 * Now do the dirty work of updating all the locations
25088123910Sblymn 	 * that have the old background character with the new.
25188123910Sblymn 	 */
25288123910Sblymn 
25388123910Sblymn 	for (wy = 0; wy < win->maxy; wy++) {
25488123910Sblymn 		wlp = win->alines[wy];
25588123910Sblymn 		for (wx = 0; wx < win->maxx; wx++) {
256a7d2c216Sblymn 			if (wlp->line[wx].cflags & CA_BACKGROUND) {
25788123910Sblymn 				_cursesi_copy_wchar(&nbkgrnd, &wlp->line[wx]);
25888123910Sblymn 			}
25988123910Sblymn 		}
26088123910Sblymn 	}
261080c30e8Sblymn 	__touchwin(win, 0);
26288123910Sblymn 
263e124de36Sblymn }
264e124de36Sblymn 
2655fc07779Suwe 
2665fc07779Suwe int
2670b616789Suwe wbkgrnd(WINDOW *win, const cchar_t *wch)
2680b616789Suwe {
2690b616789Suwe 	__CTRACE(__CTRACE_ATTR, "wbkgrnd: (%p), '%s', %x\n",
2700b616789Suwe 	    win, (const char *)wunctrl(wch), wch->attributes);
2710b616789Suwe 
272*6348e3f3Sblymn 	if (__predict_false(win == NULL))
273*6348e3f3Sblymn 		return ERR;
274*6348e3f3Sblymn 
2750b616789Suwe 	/* ignore multi-column characters */
2760b616789Suwe 	if (!wch->elements || wcwidth( wch->vals[ 0 ]) > 1)
2770b616789Suwe 		return ERR;
2780b616789Suwe 
2790b616789Suwe 	wbkgrndset(win, wch);
280301bf8ccSblymn 	__touchwin(win, 1);
2810b616789Suwe 	return OK;
2820b616789Suwe }
2830b616789Suwe 
2840b616789Suwe 
2850b616789Suwe int
2865fc07779Suwe wgetbkgrnd(WINDOW *win, cchar_t *wch)
287e124de36Sblymn {
288e124de36Sblymn 	nschar_t *np;
289e124de36Sblymn 
290*6348e3f3Sblymn 	if (__predict_false(win == NULL))
291*6348e3f3Sblymn 		return ERR;
292*6348e3f3Sblymn 
293e124de36Sblymn 	/* Background attributes (check colour). */
294e124de36Sblymn 	wch->attributes = win->battr & WA_ATTRIBUTES;
29576bb9929Suwe 	if (__using_color && ((wch->attributes & __COLOR) == __default_color))
29676bb9929Suwe 		wch->attributes &= ~__COLOR;
297e124de36Sblymn 	wch->vals[0] = win->bch;
298e124de36Sblymn 	wch->elements = 1;
299e124de36Sblymn 	np = win->bnsp;
300e124de36Sblymn 	if (np) {
301e124de36Sblymn 		while (np && wch->elements < CURSES_CCHAR_MAX) {
302e124de36Sblymn 			wch->vals[wch->elements++] = np->ch;
303e124de36Sblymn 			np = np->next;
304e124de36Sblymn 		}
305e124de36Sblymn 	}
306e124de36Sblymn 
307e124de36Sblymn 	return OK;
308e124de36Sblymn }
3095fc07779Suwe 
3105fc07779Suwe #else  /* !HAVE_WCHAR */
3115fc07779Suwe 
3125fc07779Suwe void
3135fc07779Suwe bkgrndset(const cchar_t *wch)
3145fc07779Suwe {
3155fc07779Suwe 	return;
3165fc07779Suwe }
3175fc07779Suwe 
3185fc07779Suwe int
3190b616789Suwe bkgrnd(const cchar_t *wch)
3205fc07779Suwe {
3215fc07779Suwe 	return ERR;
3225fc07779Suwe }
3235fc07779Suwe 
3245fc07779Suwe 
3255fc07779Suwe int
3260b616789Suwe getbkgrnd(cchar_t *wch)
3275fc07779Suwe {
3285fc07779Suwe 	return ERR;
3295fc07779Suwe }
3305fc07779Suwe 
3315fc07779Suwe 
3325fc07779Suwe void
3335fc07779Suwe wbkgrndset(WINDOW *win, const cchar_t *wch)
3345fc07779Suwe {
3355fc07779Suwe 	return;
3365fc07779Suwe }
3375fc07779Suwe 
3385fc07779Suwe 
3395fc07779Suwe int
3400b616789Suwe wbkgrnd(WINDOW *win, const cchar_t *wch)
3410b616789Suwe {
3420b616789Suwe 	return ERR;
3430b616789Suwe }
3440b616789Suwe 
3450b616789Suwe 
3460b616789Suwe int
3475fc07779Suwe wgetbkgrnd(WINDOW *win, cchar_t *wch)
3485fc07779Suwe {
3495fc07779Suwe 	return ERR;
3505fc07779Suwe }
3515fc07779Suwe 
3525fc07779Suwe #endif /* !HAVE_WCHAR */
353