xref: /freebsd/contrib/ncurses/ncurses/tty/lib_vidattr.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
1 /****************************************************************************
2  * Copyright (c) 1998 Free Software Foundation, Inc.                        *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28 
29 /****************************************************************************
30  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32  ****************************************************************************/
33 
34 /*
35  *	vidputs(newmode, outc)
36  *
37  *	newmode is taken to be the logical 'or' of the symbols in curses.h
38  *	representing graphic renditions.  The terminal is set to be in all of
39  *	the given modes, if possible.
40  *
41  *	if the new attribute is normal
42  *		if exit-alt-char-set exists
43  *			emit it
44  *		emit exit-attribute-mode
45  *	else if set-attributes exists
46  *		use it to set exactly what you want
47  *	else
48  *		if exit-attribute-mode exists
49  *			turn off everything
50  *		else
51  *			turn off those which can be turned off and aren't in
52  *			newmode.
53  *		turn on each mode which should be on and isn't, one by one
54  *
55  *	NOTE that this algorithm won't achieve the desired mix of attributes
56  *	in some cases, but those are probably just those cases in which it is
57  *	actually impossible, anyway, so...
58  *
59  * 	NOTE that we cannot assume that there's no interaction between color
60  *	and other attribute resets.  So each time we reset color (or other
61  *	attributes) we'll have to be prepared to restore the other.
62  */
63 
64 #include <curses.priv.h>
65 #include <term.h>
66 
67 MODULE_ID("$Id: lib_vidattr.c,v 1.23 1999/06/12 21:20:41 tom Exp $")
68 
69 #define doPut(mode) TPUTS_TRACE(#mode); tputs(mode, 1, outc)
70 
71 #define TurnOn(mask,mode) \
72 	if ((turn_on & mask) && mode) { doPut(mode); }
73 
74 #define TurnOff(mask,mode) \
75 	if ((turn_off & mask) && mode) { doPut(mode); turn_off &= ~mask; }
76 
77 	/* if there is no current screen, assume we *can* do color */
78 #define SetColorsIf(why,old_attr) \
79 	if ((!SP || SP->_coloron) && (why)) { \
80 		int old_pair = PAIR_NUMBER(old_attr); \
81 		T(("old pair = %d -- new pair = %d", old_pair, pair)); \
82 		if ((pair != old_pair) \
83 		 || (reverse ^ ((old_attr & A_REVERSE) != 0))) { \
84 			_nc_do_color(pair, reverse, outc); \
85 		} \
86 	}
87 
88 int vidputs(attr_t newmode, int  (*outc)(int))
89 {
90 static attr_t previous_attr = A_NORMAL;
91 attr_t turn_on, turn_off;
92 int pair;
93 bool reverse = FALSE;
94 bool used_ncv = FALSE;
95 
96 	T((T_CALLED("vidputs(%s)"), _traceattr(newmode)));
97 
98 	/* this allows us to go on whether or not newterm() has been called */
99 	if (SP)
100 		previous_attr = SP->_current_attr;
101 
102 	T(("previous attribute was %s", _traceattr(previous_attr)));
103 
104 #if !USE_XMC_SUPPORT
105 	if ((SP != 0)
106 	 && (magic_cookie_glitch > 0))
107 		newmode &= ~(SP->_xmc_suppress);
108 #endif
109 
110 	/*
111 	 * If we have a terminal that cannot combine color with video
112 	 * attributes, use the colors in preference.
113 	 */
114 	if ((newmode & A_COLOR)
115 	 && (no_color_video > 0)) {
116 		static const struct {
117 			attr_t video;
118 			unsigned bit;
119 		} table[] = {
120 			{ A_STANDOUT,		1 },
121 			{ A_UNDERLINE,		2 },
122 			{ A_REVERSE,		4 },
123 			{ A_BLINK,		8 },
124 			{ A_DIM,		16 },
125 			{ A_BOLD, 		32 },
126 			{ A_INVIS,		64 },
127 			{ A_PROTECT,		128 },
128 			{ A_ALTCHARSET,		256 },
129 		};
130 		size_t n;
131 		for (n = 0; n < SIZEOF(table); n++) {
132 			if ((table[n].bit & no_color_video)
133 			 && (table[n].video & newmode)) {
134 				used_ncv = TRUE;
135 				if (table[n].video == A_REVERSE)
136 					reverse = TRUE;
137 				else
138 					newmode &= ~table[n].video;
139 			}
140 		}
141 	}
142 
143 	if (newmode == previous_attr)
144 		returnCode(OK);
145 
146 	pair = PAIR_NUMBER(newmode);
147 
148 	if (reverse) {
149 		newmode &= ~A_REVERSE;
150 	}
151 
152 	turn_off = (~newmode & previous_attr) & ALL_BUT_COLOR;
153 	turn_on  = (newmode & ~previous_attr) & ALL_BUT_COLOR;
154 
155 	SetColorsIf(pair == 0, previous_attr);
156 
157 	if (newmode == A_NORMAL) {
158 		if((previous_attr & A_ALTCHARSET) && exit_alt_charset_mode) {
159 			doPut(exit_alt_charset_mode);
160 			previous_attr &= ~A_ALTCHARSET;
161 		}
162 		if (previous_attr) {
163 			doPut(exit_attribute_mode);
164 			previous_attr &= ~A_COLOR;
165 		}
166 
167 		SetColorsIf(pair != 0, previous_attr);
168 	} else if (set_attributes && !used_ncv) {
169 		if (turn_on || turn_off) {
170 			TPUTS_TRACE("set_attributes");
171 			tputs(tparm(set_attributes,
172 				(newmode & A_STANDOUT) != 0,
173 				(newmode & A_UNDERLINE) != 0,
174 				(newmode & A_REVERSE) != 0,
175 				(newmode & A_BLINK) != 0,
176 				(newmode & A_DIM) != 0,
177 				(newmode & A_BOLD) != 0,
178 				(newmode & A_INVIS) != 0,
179 				(newmode & A_PROTECT) != 0,
180 				(newmode & A_ALTCHARSET) != 0), 1, outc);
181 			previous_attr &= ~A_COLOR;
182 		}
183 		SetColorsIf(pair != 0, previous_attr);
184 	} else {
185 
186 		T(("turning %s off", _traceattr(turn_off)));
187 
188 		TurnOff(A_ALTCHARSET,  exit_alt_charset_mode);
189 
190 		if (!SP || SP->_use_rmul) {
191 			TurnOff(A_UNDERLINE,   exit_underline_mode);
192 		}
193 
194 		if (!SP || SP->_use_rmso) {
195 			TurnOff(A_STANDOUT,    exit_standout_mode);
196 		}
197 
198 		if (turn_off && exit_attribute_mode) {
199 			doPut(exit_attribute_mode);
200 			turn_on  |= (newmode & (chtype)(~A_COLOR));
201 			previous_attr &= ~A_COLOR;
202 		}
203 		SetColorsIf(pair != 0, previous_attr);
204 
205 		T(("turning %s on", _traceattr(turn_on)));
206 
207 		TurnOn (A_ALTCHARSET, enter_alt_charset_mode);
208 		TurnOn (A_BLINK,      enter_blink_mode);
209 		TurnOn (A_BOLD,       enter_bold_mode);
210 		TurnOn (A_DIM,        enter_dim_mode);
211 		TurnOn (A_REVERSE,    enter_reverse_mode);
212 		TurnOn (A_STANDOUT,   enter_standout_mode);
213 		TurnOn (A_PROTECT,    enter_protected_mode);
214 		TurnOn (A_INVIS,      enter_secure_mode);
215 		TurnOn (A_UNDERLINE,  enter_underline_mode);
216 		TurnOn (A_HORIZONTAL, enter_horizontal_hl_mode);
217 		TurnOn (A_LEFT,       enter_left_hl_mode);
218 		TurnOn (A_LOW,        enter_low_hl_mode);
219 		TurnOn (A_RIGHT,      enter_right_hl_mode);
220 		TurnOn (A_TOP,        enter_top_hl_mode);
221 		TurnOn (A_VERTICAL,   enter_vertical_hl_mode);
222 	}
223 
224 	if (reverse)
225 		newmode |= A_REVERSE;
226 
227 	if (SP)
228 		SP->_current_attr = newmode;
229 	else
230 		previous_attr = newmode;
231 
232 	returnCode(OK);
233 }
234 
235 int vidattr(attr_t newmode)
236 {
237 	T((T_CALLED("vidattr(%s)"), _traceattr(newmode)));
238 
239 	returnCode(vidputs(newmode, _nc_outch));
240 }
241 
242 chtype termattrs(void)
243 {
244 	chtype attrs = A_NORMAL;
245 
246 	if (enter_alt_charset_mode)
247 		attrs |= A_ALTCHARSET;
248 
249 	if (enter_blink_mode)
250 		attrs |= A_BLINK;
251 
252 	if (enter_bold_mode)
253 		attrs |= A_BOLD;
254 
255 	if (enter_dim_mode)
256 		attrs |= A_DIM;
257 
258 	if (enter_reverse_mode)
259 		attrs |= A_REVERSE;
260 
261 	if (enter_standout_mode)
262 		attrs |= A_STANDOUT;
263 
264 	if (enter_protected_mode)
265 		attrs |= A_PROTECT;
266 
267 	if (enter_secure_mode)
268 		attrs |= A_INVIS;
269 
270 	if (enter_underline_mode)
271 		attrs |= A_UNDERLINE;
272 
273 	if (SP->_coloron)
274 		attrs |= A_COLOR;
275 
276 	return(attrs);
277 }
278 
279