20cc2b138011c528a4f162aadee7ecfedb58d239
[ncurses.git] / ncurses / tty / lib_vidattr.c
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