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