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