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