xref: /netbsd-src/lib/libcurses/attributes.c (revision f4748aaa01faf324805f9747191535eb6600f82c)
1 /*	$NetBSD: attributes.c,v 1.35 2022/10/25 06:20:01 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.35 2022/10/25 06:20:01 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 	if (__predict_false(opts != NULL))
202 		return ERR;
203 
204 	/*
205 	 * This overwrites any colour setting from the attributes
206 	 * and is compatible with ncurses.
207 	 */
208 	attr = (attr & ~__COLOR) | COLOR_PAIR(pair);
209 
210 	__wattr_off(win, WA_ATTRIBUTES);
211 	__wattr_on(win, attr);
212 	return OK;
213 }
214 
215 /*
216  * wcolor_set --
217  *	Set color pair on window
218  */
219 /* ARGSUSED */
220 int
221 wcolor_set(WINDOW *win, short pair, void *opts)
222 {
223 	__CTRACE(__CTRACE_COLOR, "wolor_set: win %p, pair %d\n", win, pair);
224 	__wcolor_set(win, (attr_t) COLOR_PAIR(pair));
225 	return OK;
226 }
227 #endif /* HAVE_WCHAR */
228 
229 
230 /*
231  * getattrs --
232  *	Get window attributes.
233  */
234 chtype
235 getattrs(WINDOW *win)
236 {
237 	if (__predict_false(win == NULL))
238 		return ERR;
239 
240 	__CTRACE(__CTRACE_ATTR, "getattrs: win %p\n", win);
241 	return((chtype) win->wattr);
242 }
243 
244 /*
245  * wattron --
246  *	Test and set attributes.
247  */
248 int
249 wattron(WINDOW *win, int attr)
250 {
251 	__CTRACE(__CTRACE_ATTR, "wattron: win %p, attr %08x\n", win, attr);
252 	return __wattr_on(win, (attr_t) attr);
253 }
254 
255 /*
256  * wattroff --
257  *	Test and unset attributes.
258  */
259 int
260 wattroff(WINDOW *win, int attr)
261 {
262 	__CTRACE(__CTRACE_ATTR, "wattroff: win %p, attr %08x\n", win, attr);
263 	return __wattr_off(win, (attr_t) attr);
264 }
265 
266 /*
267  * wattrset --
268  *	Set specific attribute modes.
269  *	Unset others.
270  */
271 int
272 wattrset(WINDOW *win, int attr)
273 {
274 	__CTRACE(__CTRACE_ATTR, "wattrset: win %p, attr %08x\n", win, attr);
275 	__wattr_off(win, __ATTRIBUTES);
276 	__wattr_on(win, (attr_t) attr);
277 	return OK;
278 }
279 
280 /*
281  * termattrs --
282  *	Get terminal attributes
283  */
284 chtype
285 termattrs(void)
286 {
287 	chtype ch = 0;
288 
289 	__CTRACE(__CTRACE_ATTR, "termattrs\n");
290 	if (exit_attribute_mode != NULL) {
291 	__CTRACE(__CTRACE_ATTR, "termattrs: have exit attribute mode\n");
292 		if (enter_blink_mode != NULL)
293 			ch |= __BLINK;
294 		if (enter_bold_mode != NULL)
295 			ch |= __BOLD;
296 		if (enter_dim_mode != NULL)
297 			ch |= __DIM;
298 		if (enter_secure_mode != NULL)
299 			ch |= __BLANK;
300 		if (enter_protected_mode != NULL)
301 			ch |= __PROTECT;
302 		if (enter_reverse_mode != NULL)
303 			ch |= __REVERSE;
304 	}
305 	if (enter_standout_mode != NULL && exit_standout_mode != NULL)
306 		ch |= __STANDOUT;
307 	if (enter_underline_mode != NULL && exit_underline_mode != NULL)
308 		ch |= __UNDERSCORE;
309 	if (enter_alt_charset_mode != NULL && exit_alt_charset_mode != NULL)
310 		ch |= __ALTCHARSET;
311 
312 	return ch;
313 }
314 
315 
316 #ifdef HAVE_WCHAR
317 /*
318  * term_attrs --
319  *	Get terminal wide attributes
320  */
321 attr_t
322 term_attrs(void)
323 {
324 	attr_t attr = 0;
325 
326 	__CTRACE(__CTRACE_ATTR, "term_attrs\n");
327 	if (exit_attribute_mode != NULL) {
328 		if (enter_blink_mode != NULL)
329 			attr |= __BLINK;
330 		if (enter_bold_mode != NULL)
331 			attr |= __BOLD;
332 		if (enter_dim_mode != NULL)
333 			attr |= __DIM;
334 		if (enter_secure_mode != NULL)
335 			attr |= __BLANK;
336 		if (enter_protected_mode != NULL)
337 			attr |= __PROTECT;
338 		if (enter_reverse_mode != NULL)
339 			attr |= __REVERSE;
340 #ifdef HAVE_WCHAR
341 		if (enter_low_hl_mode != NULL)
342 			attr |= WA_LOW;
343 		if (enter_top_hl_mode != NULL)
344 			attr |= WA_TOP;
345 		if (enter_left_hl_mode != NULL)
346 			attr |= WA_LEFT;
347 		if (enter_right_hl_mode != NULL)
348 			attr |= WA_RIGHT;
349 		if (enter_horizontal_hl_mode != NULL)
350 			attr |= WA_HORIZONTAL;
351 		if (enter_vertical_hl_mode != NULL)
352 			attr |= WA_VERTICAL;
353 #endif /* HAVE_WCHAR */
354 	}
355 	if (enter_standout_mode != NULL && exit_standout_mode != NULL)
356 		attr |= __STANDOUT;
357 	if (enter_underline_mode != NULL && exit_underline_mode != NULL)
358 		attr |= __UNDERSCORE;
359 	if (enter_alt_charset_mode != NULL && exit_alt_charset_mode != NULL)
360 		attr |= __ALTCHARSET;
361 
362 	return attr;
363 }
364 #endif /* HAVE_WCHAR */
365 
366 
367 static int
368 __wattr_on(WINDOW *win, attr_t attr)
369 {
370 	const TERMINAL *t;
371 
372 	if (__predict_false(win == NULL))
373 		return ERR;
374 
375 	t = win->screen->term;
376 
377 	__CTRACE(__CTRACE_ATTR, "wattr_on: win %p, attr %08x\n", win, attr);
378 	/* If can enter modes, set the relevant attribute bits. */
379 	if (t_exit_attribute_mode(t) != NULL) {
380 		if (attr & __BLINK && t_enter_blink_mode(t) != NULL)
381 			win->wattr |= __BLINK;
382 		if (attr & __BOLD && t_enter_bold_mode(t) != NULL)
383 			win->wattr |= __BOLD;
384 		if (attr & __DIM && t_enter_dim_mode(t) != NULL)
385 			win->wattr |= __DIM;
386 		if (attr & __BLANK && t_enter_secure_mode(t) != NULL)
387 			win->wattr |= __BLANK;
388 		if (attr & __PROTECT && t_enter_protected_mode(t) != NULL)
389 			win->wattr |= __PROTECT;
390 		if (attr & __REVERSE && t_enter_reverse_mode(t) != NULL)
391 			win->wattr |= __REVERSE;
392 #ifdef HAVE_WCHAR
393 		if (attr & WA_LOW && t_enter_low_hl_mode(t) != NULL)
394 			win->wattr |= WA_LOW;
395 		if (attr & WA_TOP && t_enter_top_hl_mode(t) != NULL)
396 			win->wattr |= WA_TOP;
397 		if (attr & WA_LEFT && t_enter_left_hl_mode(t) != NULL)
398 			win->wattr |= WA_LEFT;
399 		if (attr & WA_RIGHT && t_enter_right_hl_mode(t) != NULL)
400 			win->wattr |= WA_RIGHT;
401 		if (attr & WA_HORIZONTAL && t_enter_horizontal_hl_mode(t) != NULL)
402 			win->wattr |= WA_HORIZONTAL;
403 		if (attr & WA_VERTICAL && t_enter_vertical_hl_mode(t) != NULL)
404 			win->wattr |= WA_VERTICAL;
405 #endif /* HAVE_WCHAR */
406 	}
407 	if (attr & __STANDOUT && t_enter_standout_mode(t) != NULL &&
408 	    t_exit_standout_mode(t) != NULL)
409 		wstandout(win);
410 	if (attr & __UNDERSCORE && t_enter_underline_mode(t) != NULL &&
411 	    t_exit_underline_mode(t) != NULL)
412 		wunderscore(win);
413 	if (attr & __COLOR)
414 		__wcolor_set(win, attr);
415 	return OK;
416 }
417 
418 
419 static int
420 __wattr_off(WINDOW *win, attr_t attr)
421 {
422 	const TERMINAL *t;
423 
424 	if (__predict_false(win == NULL))
425 		return ERR;
426 
427 	t = win->screen->term;
428 
429 	__CTRACE(__CTRACE_ATTR, "wattr_off: win %p, attr %08x\n", win, attr);
430 	/* If can do exit modes, unset the relevant attribute bits. */
431 	if (t_exit_attribute_mode(t) != NULL) {
432 		if (attr & __BLINK)
433 			win->wattr &= ~__BLINK;
434 		if (attr & __BOLD)
435 			win->wattr &= ~__BOLD;
436 		if (attr & __DIM)
437 			win->wattr &= ~__DIM;
438 		if (attr & __BLANK)
439 			win->wattr &= ~__BLANK;
440 		if (attr & __PROTECT)
441 			win->wattr &= ~__PROTECT;
442 		if (attr & __REVERSE)
443 			win->wattr &= ~__REVERSE;
444 #ifdef HAVE_WCHAR
445 		if (attr & WA_LOW)
446 			win->wattr &= ~WA_LOW;
447 		if (attr & WA_TOP)
448 			win->wattr &= ~WA_TOP;
449 		if (attr & WA_LEFT)
450 			win->wattr &= ~WA_LEFT;
451 		if (attr & WA_RIGHT)
452 			win->wattr &= ~WA_RIGHT;
453 		if (attr & WA_HORIZONTAL)
454 			win->wattr &= ~WA_HORIZONTAL;
455 		if (attr & WA_VERTICAL)
456 			win->wattr &= ~WA_VERTICAL;
457 #endif /* HAVE_WCHAR */
458 	}
459 	if (attr & __STANDOUT)
460 		wstandend(win);
461 	if (attr & __UNDERSCORE)
462 		wunderend(win);
463 	if (attr & __COLOR) {
464 		if (max_colors != 0)
465 			win->wattr &= ~__COLOR;
466 	}
467 	return OK;
468 }
469 
470 
471 static void
472 __wcolor_set(WINDOW *win, attr_t attr)
473 {
474 	const TERMINAL *t;
475 
476 	if (__predict_false(win == NULL))
477 		return;
478 
479 	t = win->screen->term;
480 
481 	/* If another color pair is set, turn that off first. */
482 	win->wattr &= ~__COLOR;
483 	/* If can do color video, set the color pair bits. */
484 	if (t_max_colors(t) != 0)
485 		win->wattr |= attr & __COLOR;
486 }
487