Home | History | Annotate | Line # | Download | only in libcurses
background.c revision 1.32
      1 /*	$NetBSD: background.c,v 1.32 2022/05/05 22:02:17 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.32 2022/05/05 22:02:17 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 	/* Background character. */
     73 	if (ch & __CHARTEXT)
     74 		win->bch = (wchar_t) ch & __CHARTEXT;
     75 
     76 	/* Background attributes (check colour). */
     77 	if (__using_color && !(ch & __COLOR))
     78 		ch |= __default_color;
     79 	win->battr = (attr_t) ch & __ATTRIBUTES;
     80 }
     81 
     82 /*
     83  * wbkgd --
     84  *	Set new background attributes on the specified window and
     85  *	apply them to its contents.
     86  */
     87 int
     88 wbkgd(WINDOW *win, chtype ch)
     89 {
     90 	int y, x;
     91 
     92 	__CTRACE(__CTRACE_ATTR, "wbkgd: (%p), '%s', %08x\n",
     93 	    win, unctrl(ch & __CHARTEXT), ch & __ATTRIBUTES);
     94 	wbkgdset(win, ch);
     95 
     96 	for (y = 0; y < win->maxy; y++) {
     97 		for (x = 0; x < win->maxx; x++) {
     98 			__LDATA *cp = &win->alines[y]->line[x];
     99 
    100 			/* Update/switch background characters */
    101 			if (cp->cflags & CA_BACKGROUND)
    102 				cp->ch = win->bch;
    103 
    104 			/* Update/merge attributes */
    105 			cp->attr = win->battr | (cp->attr & __ALTCHARSET);
    106 #ifdef HAVE_WCHAR
    107 			cp->wcols = 1;
    108 #endif
    109 		}
    110 	}
    111 	__touchwin(win, 1);
    112 	return OK;
    113 }
    114 
    115 /*
    116  * getbkgd --
    117  *	Get current background attributes.
    118  */
    119 chtype
    120 getbkgd(WINDOW *win)
    121 {
    122 	attr_t	battr;
    123 
    124 	/* Background attributes (check colour). */
    125 	battr = win->battr & A_ATTRIBUTES;
    126 	if (__using_color && ((battr & __COLOR) == __default_color))
    127 		battr &= ~__COLOR;
    128 
    129 	return ((chtype) ((win->bch & A_CHARTEXT) | battr));
    130 }
    131 
    132 
    133 #ifdef HAVE_WCHAR
    134 
    135 void
    136 bkgrndset(const cchar_t *wch)
    137 {
    138 	wbkgrndset(stdscr, wch);
    139 }
    140 
    141 
    142 int
    143 bkgrnd(const cchar_t *wch)
    144 {
    145 	return wbkgrnd(stdscr, wch);
    146 }
    147 
    148 
    149 int
    150 getbkgrnd(cchar_t *wch)
    151 {
    152 	return wgetbkgrnd(stdscr, wch);
    153 }
    154 
    155 
    156 void
    157 wbkgrndset(WINDOW *win, const cchar_t *wch)
    158 {
    159 	attr_t battr;
    160 	nschar_t *np, *tnp;
    161 	int i, wy, wx;
    162 	__LDATA obkgrnd, nbkgrnd;
    163 	__LINE *wlp;
    164 
    165 	__CTRACE(__CTRACE_ATTR, "wbkgrndset: (%p), '%s', %x\n",
    166 	    win, (const char *)wunctrl(wch), wch->attributes);
    167 
    168 	/* ignore multi-column characters */
    169 	if (!wch->elements || wcwidth(wch->vals[0]) > 1)
    170 		return;
    171 
    172 	/* get a copy of the old background, we will need it. */
    173 	obkgrnd.ch = win->bch;
    174 	obkgrnd.attr = win->battr;
    175 	obkgrnd.cflags |= CA_BACKGROUND;
    176 	obkgrnd.wcols = win->wcols;
    177 	obkgrnd.nsp = NULL;
    178 	_cursesi_copy_nsp(win->bnsp, &obkgrnd);
    179 
    180 	/* Background character. */
    181 	tnp = np = win->bnsp;
    182 	if (wcwidth( wch->vals[0]))
    183 		win->bch = wch->vals[0];
    184 	else {
    185 		if (!np) {
    186 			np = malloc(sizeof(nschar_t));
    187 			if (!np)
    188 				return;
    189 			np->next = NULL;
    190 			win->bnsp = np;
    191 		}
    192 		np->ch = wch->vals[0];
    193 		tnp = np;
    194 		np = np->next;
    195 	}
    196 	/* add non-spacing characters */
    197 	if (wch->elements > 1) {
    198 		for (i = 1; i < wch->elements; i++) {
    199 			if ( !np ) {
    200 				np = malloc(sizeof(nschar_t));
    201 				if (!np)
    202 					return;
    203 				np->next = NULL;
    204 				if (tnp)
    205 					tnp->next = np;
    206 				else
    207 					win->bnsp = np;
    208 			}
    209 			np->ch = wch->vals[i];
    210 			tnp = np;
    211 			np = np->next;
    212 		}
    213 	}
    214 	/* clear the old non-spacing characters */
    215 	__cursesi_free_nsp(np);
    216 
    217 	/* Background attributes (check colour). */
    218 	battr = wch->attributes & WA_ATTRIBUTES;
    219 	if (__using_color && !( battr & __COLOR))
    220 		battr |= __default_color;
    221 	win->battr = battr;
    222 	win->wcols = 1;
    223 
    224 	nbkgrnd.ch = win->bch;
    225 	nbkgrnd.attr = win->battr;
    226 	nbkgrnd.cflags |= CA_BACKGROUND;
    227 	nbkgrnd.wcols = win->wcols;
    228 	nbkgrnd.nsp = NULL;
    229 	_cursesi_copy_nsp(win->bnsp, &nbkgrnd);
    230 
    231 	/* if the background is already this char then skip updating */
    232 	if (_cursesi_celleq(&obkgrnd, &nbkgrnd))
    233 		return;
    234 
    235 	/*
    236 	 * Now do the dirty work of updating all the locations
    237 	 * that have the old background character with the new.
    238 	 */
    239 
    240 	for (wy = 0; wy < win->maxy; wy++) {
    241 		wlp = win->alines[wy];
    242 		for (wx = 0; wx < win->maxx; wx++) {
    243 			if (wlp->line[wx].cflags & CA_BACKGROUND) {
    244 				_cursesi_copy_wchar(&nbkgrnd, &wlp->line[wx]);
    245 			}
    246 		}
    247 	}
    248 	__touchwin(win, 0);
    249 
    250 }
    251 
    252 
    253 int
    254 wbkgrnd(WINDOW *win, const cchar_t *wch)
    255 {
    256 	__CTRACE(__CTRACE_ATTR, "wbkgrnd: (%p), '%s', %x\n",
    257 	    win, (const char *)wunctrl(wch), wch->attributes);
    258 
    259 	/* ignore multi-column characters */
    260 	if (!wch->elements || wcwidth( wch->vals[ 0 ]) > 1)
    261 		return ERR;
    262 
    263 	wbkgrndset(win, wch);
    264 	__touchwin(win, 1);
    265 	return OK;
    266 }
    267 
    268 
    269 int
    270 wgetbkgrnd(WINDOW *win, cchar_t *wch)
    271 {
    272 	nschar_t *np;
    273 
    274 	/* Background attributes (check colour). */
    275 	wch->attributes = win->battr & WA_ATTRIBUTES;
    276 	if (__using_color && ((wch->attributes & __COLOR) == __default_color))
    277 		wch->attributes &= ~__COLOR;
    278 	wch->vals[0] = win->bch;
    279 	wch->elements = 1;
    280 	np = win->bnsp;
    281 	if (np) {
    282 		while (np && wch->elements < CURSES_CCHAR_MAX) {
    283 			wch->vals[wch->elements++] = np->ch;
    284 			np = np->next;
    285 		}
    286 	}
    287 
    288 	return OK;
    289 }
    290 
    291 #else  /* !HAVE_WCHAR */
    292 
    293 void
    294 bkgrndset(const cchar_t *wch)
    295 {
    296 	return;
    297 }
    298 
    299 int
    300 bkgrnd(const cchar_t *wch)
    301 {
    302 	return ERR;
    303 }
    304 
    305 
    306 int
    307 getbkgrnd(cchar_t *wch)
    308 {
    309 	return ERR;
    310 }
    311 
    312 
    313 void
    314 wbkgrndset(WINDOW *win, const cchar_t *wch)
    315 {
    316 	return;
    317 }
    318 
    319 
    320 int
    321 wbkgrnd(WINDOW *win, const cchar_t *wch)
    322 {
    323 	return ERR;
    324 }
    325 
    326 
    327 int
    328 wgetbkgrnd(WINDOW *win, cchar_t *wch)
    329 {
    330 	return ERR;
    331 }
    332 
    333 #endif /* !HAVE_WCHAR */
    334