1/* $NetBSD: background.c,v 1.33 2022/10/19 06:09:27 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.33 2022/10/19 06:09:27 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 */ 45void 46bkgdset(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 */ 56int 57bkgd(chtype ch) 58{ 59 return(wbkgd(stdscr, ch)); 60} 61 62/* 63 * wbkgdset 64 * Set new background attributes on the specified window. 65 */ 66void 67wbkgdset(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 */ 87int 88wbkgd(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 */ 119chtype 120getbkgd(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 135void 136bkgrndset(const cchar_t *wch) 137{ 138 wbkgrndset(stdscr, wch); 139} 140 141 142int 143bkgrnd(const cchar_t *wch) 144{ 145 return wbkgrnd(stdscr, wch); 146} 147 148 149int 150getbkgrnd(cchar_t *wch) 151{ 152 return wgetbkgrnd(stdscr, wch); 153} 154 155 156void 157wbkgrndset(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 253int 254wbkgrnd(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 269int 270wgetbkgrnd(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 293void 294bkgrndset(const cchar_t *wch) 295{ 296 return; 297} 298 299int 300bkgrnd(const cchar_t *wch) 301{ 302 return ERR; 303} 304 305 306int 307getbkgrnd(cchar_t *wch) 308{ 309 return ERR; 310} 311 312 313void 314wbkgrndset(WINDOW *win, const cchar_t *wch) 315{ 316 return; 317} 318 319 320int 321wbkgrnd(WINDOW *win, const cchar_t *wch) 322{ 323 return ERR; 324} 325 326 327int 328wgetbkgrnd(WINDOW *win, cchar_t *wch) 329{ 330 return ERR; 331} 332 333#endif /* !HAVE_WCHAR */ 334