xref: /netbsd-src/lib/libcurses/background.c (revision 6348e3f32a4431b45d07e1da16fd7b12725a45e7)
1 /*	$NetBSD: background.c,v 1.34 2024/12/23 02:58:03 blymn Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Julian Coleman.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: background.c,v 1.34 2024/12/23 02:58:03 blymn Exp $");
35 #endif				/* not lint */
36 
37 #include <stdlib.h>
38 #include "curses.h"
39 #include "curses_private.h"
40 
41 /*
42  * bkgdset
43  *	Set new background attributes on stdscr.
44  */
45 void
46 bkgdset(chtype ch)
47 {
48 	wbkgdset(stdscr, ch);
49 }
50 
51 /*
52  * bkgd --
53  *	Set new background attributes on stdscr and apply them to its
54  *	contents.
55  */
56 int
57 bkgd(chtype ch)
58 {
59 	return(wbkgd(stdscr, ch));
60 }
61 
62 /*
63  * wbkgdset
64  *	Set new background attributes on the specified window.
65  */
66 void
67 wbkgdset(WINDOW *win, chtype ch)
68 {
69 	__CTRACE(__CTRACE_ATTR, "wbkgdset: (%p), '%s', %08x\n",
70 	    win, unctrl(ch & __CHARTEXT), ch & __ATTRIBUTES);
71 
72 	if (__predict_false(win == NULL))
73 		return;
74 
75 	/* Background character. */
76 	if (ch & __CHARTEXT)
77 		win->bch = (wchar_t) ch & __CHARTEXT;
78 
79 	/* Background attributes (check colour). */
80 	if (__using_color && !(ch & __COLOR))
81 		ch |= __default_color;
82 	win->battr = (attr_t) ch & __ATTRIBUTES;
83 }
84 
85 /*
86  * wbkgd --
87  *	Set new background attributes on the specified window and
88  *	apply them to its contents.
89  */
90 int
91 wbkgd(WINDOW *win, chtype ch)
92 {
93 	int y, x;
94 
95 	__CTRACE(__CTRACE_ATTR, "wbkgd: (%p), '%s', %08x\n",
96 	    win, unctrl(ch & __CHARTEXT), ch & __ATTRIBUTES);
97 
98 	if (__predict_false(win == NULL))
99 		return ERR;
100 
101 	wbkgdset(win, ch);
102 
103 	for (y = 0; y < win->maxy; y++) {
104 		for (x = 0; x < win->maxx; x++) {
105 			__LDATA *cp = &win->alines[y]->line[x];
106 
107 			/* Update/switch background characters */
108 			if (cp->cflags & CA_BACKGROUND)
109 				cp->ch = win->bch;
110 
111 			/* Update/merge attributes */
112 			cp->attr = win->battr | (cp->attr & __ALTCHARSET);
113 #ifdef HAVE_WCHAR
114 			cp->wcols = 1;
115 #endif
116 		}
117 	}
118 	__touchwin(win, 1);
119 	return OK;
120 }
121 
122 /*
123  * getbkgd --
124  *	Get current background attributes.
125  */
126 chtype
127 getbkgd(WINDOW *win)
128 {
129 	attr_t	battr;
130 
131 	if (__predict_false(win == NULL))
132 		return ERR;
133 
134 	/* Background attributes (check colour). */
135 	battr = win->battr & A_ATTRIBUTES;
136 	if (__using_color && ((battr & __COLOR) == __default_color))
137 		battr &= ~__COLOR;
138 
139 	return ((chtype) ((win->bch & A_CHARTEXT) | battr));
140 }
141 
142 
143 #ifdef HAVE_WCHAR
144 
145 void
146 bkgrndset(const cchar_t *wch)
147 {
148 	wbkgrndset(stdscr, wch);
149 }
150 
151 
152 int
153 bkgrnd(const cchar_t *wch)
154 {
155 	return wbkgrnd(stdscr, wch);
156 }
157 
158 
159 int
160 getbkgrnd(cchar_t *wch)
161 {
162 	return wgetbkgrnd(stdscr, wch);
163 }
164 
165 
166 void
167 wbkgrndset(WINDOW *win, const cchar_t *wch)
168 {
169 	attr_t battr;
170 	nschar_t *np, *tnp;
171 	int i, wy, wx;
172 	__LDATA obkgrnd, nbkgrnd;
173 	__LINE *wlp;
174 
175 	__CTRACE(__CTRACE_ATTR, "wbkgrndset: (%p), '%s', %x\n",
176 	    win, (const char *)wunctrl(wch), wch->attributes);
177 
178 	if (__predict_false(win == NULL))
179 		return;
180 
181 	/* ignore multi-column characters */
182 	if (!wch->elements || wcwidth(wch->vals[0]) > 1)
183 		return;
184 
185 	/* get a copy of the old background, we will need it. */
186 	obkgrnd.ch = win->bch;
187 	obkgrnd.attr = win->battr;
188 	obkgrnd.cflags = CA_BACKGROUND;
189 	obkgrnd.wcols = win->wcols;
190 	obkgrnd.nsp = NULL;
191 	_cursesi_copy_nsp(win->bnsp, &obkgrnd);
192 
193 	/* Background character. */
194 	tnp = np = win->bnsp;
195 	if (wcwidth( wch->vals[0]))
196 		win->bch = wch->vals[0];
197 	else {
198 		if (!np) {
199 			np = malloc(sizeof(nschar_t));
200 			if (!np)
201 				return;
202 			np->next = NULL;
203 			win->bnsp = np;
204 		}
205 		np->ch = wch->vals[0];
206 		tnp = np;
207 		np = np->next;
208 	}
209 	/* add non-spacing characters */
210 	if (wch->elements > 1) {
211 		for (i = 1; i < wch->elements; i++) {
212 			if ( !np ) {
213 				np = malloc(sizeof(nschar_t));
214 				if (!np)
215 					return;
216 				np->next = NULL;
217 				if (tnp)
218 					tnp->next = np;
219 				else
220 					win->bnsp = np;
221 			}
222 			np->ch = wch->vals[i];
223 			tnp = np;
224 			np = np->next;
225 		}
226 	}
227 	/* clear the old non-spacing characters */
228 	__cursesi_free_nsp(np);
229 
230 	/* Background attributes (check colour). */
231 	battr = wch->attributes & WA_ATTRIBUTES;
232 	if (__using_color && !( battr & __COLOR))
233 		battr |= __default_color;
234 	win->battr = battr;
235 	win->wcols = 1;
236 
237 	nbkgrnd.ch = win->bch;
238 	nbkgrnd.attr = win->battr;
239 	nbkgrnd.cflags = CA_BACKGROUND;
240 	nbkgrnd.wcols = win->wcols;
241 	nbkgrnd.nsp = NULL;
242 	_cursesi_copy_nsp(win->bnsp, &nbkgrnd);
243 
244 	/* if the background is already this char then skip updating */
245 	if (_cursesi_celleq(&obkgrnd, &nbkgrnd))
246 		return;
247 
248 	/*
249 	 * Now do the dirty work of updating all the locations
250 	 * that have the old background character with the new.
251 	 */
252 
253 	for (wy = 0; wy < win->maxy; wy++) {
254 		wlp = win->alines[wy];
255 		for (wx = 0; wx < win->maxx; wx++) {
256 			if (wlp->line[wx].cflags & CA_BACKGROUND) {
257 				_cursesi_copy_wchar(&nbkgrnd, &wlp->line[wx]);
258 			}
259 		}
260 	}
261 	__touchwin(win, 0);
262 
263 }
264 
265 
266 int
267 wbkgrnd(WINDOW *win, const cchar_t *wch)
268 {
269 	__CTRACE(__CTRACE_ATTR, "wbkgrnd: (%p), '%s', %x\n",
270 	    win, (const char *)wunctrl(wch), wch->attributes);
271 
272 	if (__predict_false(win == NULL))
273 		return ERR;
274 
275 	/* ignore multi-column characters */
276 	if (!wch->elements || wcwidth( wch->vals[ 0 ]) > 1)
277 		return ERR;
278 
279 	wbkgrndset(win, wch);
280 	__touchwin(win, 1);
281 	return OK;
282 }
283 
284 
285 int
286 wgetbkgrnd(WINDOW *win, cchar_t *wch)
287 {
288 	nschar_t *np;
289 
290 	if (__predict_false(win == NULL))
291 		return ERR;
292 
293 	/* Background attributes (check colour). */
294 	wch->attributes = win->battr & WA_ATTRIBUTES;
295 	if (__using_color && ((wch->attributes & __COLOR) == __default_color))
296 		wch->attributes &= ~__COLOR;
297 	wch->vals[0] = win->bch;
298 	wch->elements = 1;
299 	np = win->bnsp;
300 	if (np) {
301 		while (np && wch->elements < CURSES_CCHAR_MAX) {
302 			wch->vals[wch->elements++] = np->ch;
303 			np = np->next;
304 		}
305 	}
306 
307 	return OK;
308 }
309 
310 #else  /* !HAVE_WCHAR */
311 
312 void
313 bkgrndset(const cchar_t *wch)
314 {
315 	return;
316 }
317 
318 int
319 bkgrnd(const cchar_t *wch)
320 {
321 	return ERR;
322 }
323 
324 
325 int
326 getbkgrnd(cchar_t *wch)
327 {
328 	return ERR;
329 }
330 
331 
332 void
333 wbkgrndset(WINDOW *win, const cchar_t *wch)
334 {
335 	return;
336 }
337 
338 
339 int
340 wbkgrnd(WINDOW *win, const cchar_t *wch)
341 {
342 	return ERR;
343 }
344 
345 
346 int
347 wgetbkgrnd(WINDOW *win, cchar_t *wch)
348 {
349 	return ERR;
350 }
351 
352 #endif /* !HAVE_WCHAR */
353