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