1 /* $NetBSD: attributes.c,v 1.36 2024/12/23 02:58:03 blymn Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 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: attributes.c,v 1.36 2024/12/23 02:58:03 blymn Exp $"); 35 #endif /* not lint */ 36 37 #include "curses.h" 38 #include "curses_private.h" 39 40 static int __wattr_off(WINDOW *, attr_t); 41 static int __wattr_on(WINDOW *, attr_t); 42 static void __wcolor_set(WINDOW *, attr_t); 43 44 45 #ifndef _CURSES_USE_MACROS 46 #ifdef HAVE_WCHAR 47 /* 48 * attr_get -- 49 * Get wide attributes and color pair from stdscr 50 */ 51 /* ARGSUSED */ 52 int 53 attr_get(attr_t *attr, short *pair, void *opts) 54 { 55 return wattr_get(stdscr, attr, pair, opts); 56 } 57 58 /* 59 * attr_on -- 60 * Test and set wide attributes on stdscr 61 */ 62 /* ARGSUSED */ 63 int 64 attr_on(attr_t attr, void *opts) 65 { 66 return wattr_on(stdscr, attr, opts); 67 } 68 69 /* 70 * attr_off -- 71 * Test and unset wide attributes on stdscr 72 */ 73 /* ARGSUSED */ 74 int 75 attr_off(attr_t attr, void *opts) 76 { 77 return wattr_off(stdscr, attr, opts); 78 } 79 80 /* 81 * attr_set -- 82 * Set wide attributes and color pair on stdscr 83 */ 84 /* ARGSUSED */ 85 int 86 attr_set(attr_t attr, short pair, void *opts) 87 { 88 return wattr_set(stdscr, attr, pair, opts); 89 } 90 91 /* 92 * color_set -- 93 * Set color pair on stdscr 94 */ 95 /* ARGSUSED */ 96 int 97 color_set(short pair, void *opts) 98 { 99 return wcolor_set(stdscr, pair, opts); 100 } 101 #endif /* HAVE_WCHAR */ 102 103 /* 104 * attron -- 105 * Test and set attributes on stdscr 106 */ 107 int 108 attron(int attr) 109 { 110 return wattron(stdscr, attr); 111 } 112 113 /* 114 * attroff -- 115 * Test and unset attributes on stdscr. 116 */ 117 int 118 attroff(int attr) 119 { 120 return wattroff(stdscr, attr); 121 } 122 123 /* 124 * attrset -- 125 * Set specific attribute modes. 126 * Unset others. On stdscr. 127 */ 128 int 129 attrset(int attr) 130 { 131 return wattrset(stdscr, attr); 132 } 133 #endif /* _CURSES_USE_MACROS */ 134 135 136 #ifdef HAVE_WCHAR 137 /* 138 * wattr_get -- 139 * Get wide attributes and colour pair from window 140 * Note that attributes also includes colour. 141 */ 142 /* ARGSUSED */ 143 int 144 wattr_get(WINDOW *win, attr_t *attr, short *pair, void *opts) 145 { 146 if (__predict_false(win == NULL)) 147 return ERR; 148 149 __CTRACE(__CTRACE_ATTR, "wattr_get: win %p\n", win); 150 if (attr != NULL) { 151 *attr = win->wattr; 152 #ifdef HAVE_WCHAR 153 *attr &= WA_ATTRIBUTES; 154 #endif 155 } 156 157 if (pair != NULL) 158 *pair = PAIR_NUMBER(win->wattr); 159 return OK; 160 } 161 162 /* 163 * wattr_on -- 164 * Test and set wide attributes on window 165 */ 166 int 167 wattr_on(WINDOW *win, attr_t attr, void *opts) 168 { 169 if (__predict_false(opts != NULL)) 170 return ERR; 171 172 return __wattr_on(win, attr); 173 } 174 175 /* 176 * wattr_off -- 177 * Test and unset wide attributes on window 178 * 179 * Note that the 'me' sequence unsets all attributes. We handle 180 * which attributes should really be set in refresh.c:makech(). 181 */ 182 int 183 wattr_off(WINDOW *win, attr_t attr, void *opts) 184 { 185 if (__predict_false(opts != NULL)) 186 return ERR; 187 188 return __wattr_off(win, attr); 189 } 190 191 192 /* 193 * wattr_set -- 194 * Set wide attributes and color pair on window 195 */ 196 int 197 wattr_set(WINDOW *win, attr_t attr, short pair, void *opts) 198 { 199 __CTRACE(__CTRACE_ATTR, "wattr_set: win %p, attr %08x, pair %d\n", 200 win, attr, pair); 201 202 if (__predict_false(opts != NULL)) 203 return ERR; 204 205 /* 206 * This overwrites any colour setting from the attributes 207 * and is compatible with ncurses. 208 */ 209 attr = (attr & ~__COLOR) | COLOR_PAIR(pair); 210 211 __wattr_off(win, WA_ATTRIBUTES); 212 __wattr_on(win, attr); 213 return OK; 214 } 215 216 /* 217 * wcolor_set -- 218 * Set color pair on window 219 */ 220 /* ARGSUSED */ 221 int 222 wcolor_set(WINDOW *win, short pair, void *opts) 223 { 224 __CTRACE(__CTRACE_COLOR, "wolor_set: win %p, pair %d\n", win, pair); 225 226 if (__predict_false(opts != NULL)) 227 return ERR; 228 229 __wcolor_set(win, (attr_t) COLOR_PAIR(pair)); 230 return OK; 231 } 232 #endif /* HAVE_WCHAR */ 233 234 235 /* 236 * getattrs -- 237 * Get window attributes. 238 */ 239 chtype 240 getattrs(WINDOW *win) 241 { 242 if (__predict_false(win == NULL)) 243 return ERR; 244 245 __CTRACE(__CTRACE_ATTR, "getattrs: win %p\n", win); 246 return((chtype) win->wattr); 247 } 248 249 /* 250 * wattron -- 251 * Test and set attributes. 252 */ 253 int 254 wattron(WINDOW *win, int attr) 255 { 256 __CTRACE(__CTRACE_ATTR, "wattron: win %p, attr %08x\n", win, attr); 257 return __wattr_on(win, (attr_t) attr); 258 } 259 260 /* 261 * wattroff -- 262 * Test and unset attributes. 263 */ 264 int 265 wattroff(WINDOW *win, int attr) 266 { 267 __CTRACE(__CTRACE_ATTR, "wattroff: win %p, attr %08x\n", win, attr); 268 return __wattr_off(win, (attr_t) attr); 269 } 270 271 /* 272 * wattrset -- 273 * Set specific attribute modes. 274 * Unset others. 275 */ 276 int 277 wattrset(WINDOW *win, int attr) 278 { 279 __CTRACE(__CTRACE_ATTR, "wattrset: win %p, attr %08x\n", win, attr); 280 __wattr_off(win, __ATTRIBUTES); 281 __wattr_on(win, (attr_t) attr); 282 return OK; 283 } 284 285 /* 286 * termattrs -- 287 * Get terminal attributes 288 */ 289 chtype 290 termattrs(void) 291 { 292 chtype ch = 0; 293 294 __CTRACE(__CTRACE_ATTR, "termattrs\n"); 295 if (exit_attribute_mode != NULL) { 296 __CTRACE(__CTRACE_ATTR, "termattrs: have exit attribute mode\n"); 297 if (enter_blink_mode != NULL) 298 ch |= __BLINK; 299 if (enter_bold_mode != NULL) 300 ch |= __BOLD; 301 if (enter_dim_mode != NULL) 302 ch |= __DIM; 303 if (enter_secure_mode != NULL) 304 ch |= __BLANK; 305 if (enter_protected_mode != NULL) 306 ch |= __PROTECT; 307 if (enter_reverse_mode != NULL) 308 ch |= __REVERSE; 309 } 310 if (enter_standout_mode != NULL && exit_standout_mode != NULL) 311 ch |= __STANDOUT; 312 if (enter_underline_mode != NULL && exit_underline_mode != NULL) 313 ch |= __UNDERSCORE; 314 if (enter_alt_charset_mode != NULL && exit_alt_charset_mode != NULL) 315 ch |= __ALTCHARSET; 316 317 return ch; 318 } 319 320 321 #ifdef HAVE_WCHAR 322 /* 323 * term_attrs -- 324 * Get terminal wide attributes 325 */ 326 attr_t 327 term_attrs(void) 328 { 329 attr_t attr = 0; 330 331 __CTRACE(__CTRACE_ATTR, "term_attrs\n"); 332 if (exit_attribute_mode != NULL) { 333 if (enter_blink_mode != NULL) 334 attr |= __BLINK; 335 if (enter_bold_mode != NULL) 336 attr |= __BOLD; 337 if (enter_dim_mode != NULL) 338 attr |= __DIM; 339 if (enter_secure_mode != NULL) 340 attr |= __BLANK; 341 if (enter_protected_mode != NULL) 342 attr |= __PROTECT; 343 if (enter_reverse_mode != NULL) 344 attr |= __REVERSE; 345 #ifdef HAVE_WCHAR 346 if (enter_low_hl_mode != NULL) 347 attr |= WA_LOW; 348 if (enter_top_hl_mode != NULL) 349 attr |= WA_TOP; 350 if (enter_left_hl_mode != NULL) 351 attr |= WA_LEFT; 352 if (enter_right_hl_mode != NULL) 353 attr |= WA_RIGHT; 354 if (enter_horizontal_hl_mode != NULL) 355 attr |= WA_HORIZONTAL; 356 if (enter_vertical_hl_mode != NULL) 357 attr |= WA_VERTICAL; 358 #endif /* HAVE_WCHAR */ 359 } 360 if (enter_standout_mode != NULL && exit_standout_mode != NULL) 361 attr |= __STANDOUT; 362 if (enter_underline_mode != NULL && exit_underline_mode != NULL) 363 attr |= __UNDERSCORE; 364 if (enter_alt_charset_mode != NULL && exit_alt_charset_mode != NULL) 365 attr |= __ALTCHARSET; 366 367 return attr; 368 } 369 #endif /* HAVE_WCHAR */ 370 371 372 static int 373 __wattr_on(WINDOW *win, attr_t attr) 374 { 375 const TERMINAL *t; 376 377 if (__predict_false(win == NULL)) 378 return ERR; 379 380 t = win->screen->term; 381 382 __CTRACE(__CTRACE_ATTR, "wattr_on: win %p, attr %08x\n", win, attr); 383 /* If can enter modes, set the relevant attribute bits. */ 384 if (t_exit_attribute_mode(t) != NULL) { 385 if (attr & __BLINK && t_enter_blink_mode(t) != NULL) 386 win->wattr |= __BLINK; 387 if (attr & __BOLD && t_enter_bold_mode(t) != NULL) 388 win->wattr |= __BOLD; 389 if (attr & __DIM && t_enter_dim_mode(t) != NULL) 390 win->wattr |= __DIM; 391 if (attr & __BLANK && t_enter_secure_mode(t) != NULL) 392 win->wattr |= __BLANK; 393 if (attr & __PROTECT && t_enter_protected_mode(t) != NULL) 394 win->wattr |= __PROTECT; 395 if (attr & __REVERSE && t_enter_reverse_mode(t) != NULL) 396 win->wattr |= __REVERSE; 397 #ifdef HAVE_WCHAR 398 if (attr & WA_LOW && t_enter_low_hl_mode(t) != NULL) 399 win->wattr |= WA_LOW; 400 if (attr & WA_TOP && t_enter_top_hl_mode(t) != NULL) 401 win->wattr |= WA_TOP; 402 if (attr & WA_LEFT && t_enter_left_hl_mode(t) != NULL) 403 win->wattr |= WA_LEFT; 404 if (attr & WA_RIGHT && t_enter_right_hl_mode(t) != NULL) 405 win->wattr |= WA_RIGHT; 406 if (attr & WA_HORIZONTAL && t_enter_horizontal_hl_mode(t) != NULL) 407 win->wattr |= WA_HORIZONTAL; 408 if (attr & WA_VERTICAL && t_enter_vertical_hl_mode(t) != NULL) 409 win->wattr |= WA_VERTICAL; 410 #endif /* HAVE_WCHAR */ 411 } 412 if (attr & __STANDOUT && t_enter_standout_mode(t) != NULL && 413 t_exit_standout_mode(t) != NULL) 414 wstandout(win); 415 if (attr & __UNDERSCORE && t_enter_underline_mode(t) != NULL && 416 t_exit_underline_mode(t) != NULL) 417 wunderscore(win); 418 if (attr & __COLOR) 419 __wcolor_set(win, attr); 420 return OK; 421 } 422 423 424 static int 425 __wattr_off(WINDOW *win, attr_t attr) 426 { 427 const TERMINAL *t; 428 429 if (__predict_false(win == NULL)) 430 return ERR; 431 432 t = win->screen->term; 433 434 __CTRACE(__CTRACE_ATTR, "wattr_off: win %p, attr %08x\n", win, attr); 435 /* If can do exit modes, unset the relevant attribute bits. */ 436 if (t_exit_attribute_mode(t) != NULL) { 437 if (attr & __BLINK) 438 win->wattr &= ~__BLINK; 439 if (attr & __BOLD) 440 win->wattr &= ~__BOLD; 441 if (attr & __DIM) 442 win->wattr &= ~__DIM; 443 if (attr & __BLANK) 444 win->wattr &= ~__BLANK; 445 if (attr & __PROTECT) 446 win->wattr &= ~__PROTECT; 447 if (attr & __REVERSE) 448 win->wattr &= ~__REVERSE; 449 #ifdef HAVE_WCHAR 450 if (attr & WA_LOW) 451 win->wattr &= ~WA_LOW; 452 if (attr & WA_TOP) 453 win->wattr &= ~WA_TOP; 454 if (attr & WA_LEFT) 455 win->wattr &= ~WA_LEFT; 456 if (attr & WA_RIGHT) 457 win->wattr &= ~WA_RIGHT; 458 if (attr & WA_HORIZONTAL) 459 win->wattr &= ~WA_HORIZONTAL; 460 if (attr & WA_VERTICAL) 461 win->wattr &= ~WA_VERTICAL; 462 #endif /* HAVE_WCHAR */ 463 } 464 if (attr & __STANDOUT) 465 wstandend(win); 466 if (attr & __UNDERSCORE) 467 wunderend(win); 468 if (attr & __COLOR) { 469 if (max_colors != 0) 470 win->wattr &= ~__COLOR; 471 } 472 return OK; 473 } 474 475 476 static void 477 __wcolor_set(WINDOW *win, attr_t attr) 478 { 479 const TERMINAL *t; 480 481 if (__predict_false(win == NULL)) 482 return; 483 484 t = win->screen->term; 485 486 /* If another color pair is set, turn that off first. */ 487 win->wattr &= ~__COLOR; 488 /* If can do color video, set the color pair bits. */ 489 if (t_max_colors(t) != 0) 490 win->wattr |= attr & __COLOR; 491 } 492