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