ncurses 4.2
[ncurses.git] / ncurses / 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.20 1998/02/11 12:13:56 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 int vidputs(attr_t newmode, int  (*outc)(int))
78 {
79 static attr_t previous_attr = A_NORMAL;
80 attr_t turn_on, turn_off;
81 int pair, current_pair;
82 bool reverse = FALSE;
83 bool used_ncv = FALSE;
84
85         T((T_CALLED("vidputs(%s)"), _traceattr(newmode)));
86
87         /* this allows us to go on whether or not newterm() has been called */
88         if (SP)
89                 previous_attr = SP->_current_attr;
90
91         T(("previous attribute was %s", _traceattr(previous_attr)));
92
93 #if !USE_XMC_SUPPORT
94         if (magic_cookie_glitch > 0)
95                 newmode &= ~(SP->_xmc_suppress);
96 #endif
97
98         /*
99          * If we have a terminal that cannot combine color with video
100          * attributes, use the colors in preference.
101          */
102         if ((newmode & A_COLOR)
103          && (no_color_video > 0)) {
104                 static const struct {
105                         attr_t video;
106                         unsigned bit;
107                 } table[] = {
108                         { A_STANDOUT,           1 },
109                         { A_UNDERLINE,          2 },
110                         { A_REVERSE,            4 },
111                         { A_BLINK,              8 },
112                         { A_DIM,                16 },
113                         { A_BOLD,               32 },
114                         { A_INVIS,              64 },
115                         { A_PROTECT,            128 },
116                         { A_ALTCHARSET,         256 },
117                 };
118                 size_t n;
119                 for (n = 0; n < SIZEOF(table); n++) {
120                         if ((table[n].bit & no_color_video)
121                          && (table[n].video & newmode)) {
122                                 used_ncv = TRUE;
123                                 if (table[n].video == A_REVERSE)
124                                         reverse = TRUE;
125                                 else
126                                         newmode &= ~table[n].video;
127                         }
128                 }
129         }
130
131         if (newmode == previous_attr)
132                 returnCode(OK);
133
134         pair = PAIR_NUMBER(newmode);
135         current_pair = PAIR_NUMBER(previous_attr);
136
137         if (reverse) {
138                 newmode &= ~A_REVERSE;
139                 pair = -pair;
140         }
141         if (previous_attr & A_REVERSE)
142                 current_pair = -current_pair;
143
144         turn_off = (~newmode & previous_attr) & ALL_BUT_COLOR;
145         turn_on  = (newmode & ~previous_attr) & ALL_BUT_COLOR;
146
147         /* if there is no current screen, assume we *can* do color */
148         if ((!SP || SP->_coloron) && pair == 0) {
149                 T(("old pair = %d -- new pair = %d", current_pair, pair));
150                 if (pair != current_pair) {
151                         _nc_do_color(pair, reverse, outc);
152                         previous_attr &= ~A_COLOR;
153                 }
154         }
155
156         if (newmode == A_NORMAL) {
157                 if((previous_attr & A_ALTCHARSET) && exit_alt_charset_mode) {
158                         doPut(exit_alt_charset_mode);
159                         previous_attr &= ~A_ALTCHARSET;
160                 }
161                 if (previous_attr) {
162                         doPut(exit_attribute_mode);
163                         previous_attr &= ~A_COLOR;
164                 }
165
166         } else if (set_attributes && !used_ncv) {
167                 if (turn_on || turn_off) {
168                         TPUTS_TRACE("set_attributes");
169                         tputs(tparm(set_attributes,
170                                 (newmode & A_STANDOUT) != 0,
171                                 (newmode & A_UNDERLINE) != 0,
172                                 (newmode & A_REVERSE) != 0,
173                                 (newmode & A_BLINK) != 0,
174                                 (newmode & A_DIM) != 0,
175                                 (newmode & A_BOLD) != 0,
176                                 (newmode & A_INVIS) != 0,
177                                 (newmode & A_PROTECT) != 0,
178                                 (newmode & A_ALTCHARSET) != 0), 1, outc);
179                         previous_attr &= ~A_COLOR;
180                 }
181         } else {
182
183                 T(("turning %s off", _traceattr(turn_off)));
184
185                 TurnOff(A_ALTCHARSET,  exit_alt_charset_mode);
186                 TurnOff(A_UNDERLINE,   exit_underline_mode);
187                 TurnOff(A_STANDOUT,    exit_standout_mode);
188
189                 if (turn_off && exit_attribute_mode) {
190                         doPut(exit_attribute_mode);
191                         turn_on  |= (newmode & (chtype)(~A_COLOR));
192                         previous_attr &= ~A_COLOR;
193                 }
194
195                 T(("turning %s on", _traceattr(turn_on)));
196
197                 TurnOn (A_ALTCHARSET, enter_alt_charset_mode);
198                 TurnOn (A_BLINK,      enter_blink_mode);
199                 TurnOn (A_BOLD,       enter_bold_mode);
200                 TurnOn (A_DIM,        enter_dim_mode);
201                 TurnOn (A_REVERSE,    enter_reverse_mode);
202                 TurnOn (A_STANDOUT,   enter_standout_mode);
203                 TurnOn (A_PROTECT,    enter_protected_mode);
204                 TurnOn (A_INVIS,      enter_secure_mode);
205                 TurnOn (A_UNDERLINE,  enter_underline_mode);
206                 TurnOn (A_HORIZONTAL, enter_horizontal_hl_mode);
207                 TurnOn (A_LEFT,       enter_left_hl_mode);
208                 TurnOn (A_LOW,        enter_low_hl_mode);
209                 TurnOn (A_RIGHT,      enter_right_hl_mode);
210                 TurnOn (A_TOP,        enter_top_hl_mode);
211                 TurnOn (A_VERTICAL,   enter_vertical_hl_mode);
212         }
213
214         /* if there is no current screen, assume we *can* do color */
215         if ((!SP || SP->_coloron) && pair != 0) {
216                 current_pair = PAIR_NUMBER(previous_attr);
217                 T(("old pair = %d -- new pair = %d", current_pair, pair));
218                 if (pair != current_pair) {
219                         _nc_do_color(pair, reverse, outc);
220                 }
221         }
222
223         if (reverse)
224                 newmode |= A_REVERSE;
225
226         if (SP)
227                 SP->_current_attr = newmode;
228         else
229                 previous_attr = newmode;
230
231         returnCode(OK);
232 }
233
234 int vidattr(attr_t newmode)
235 {
236         T((T_CALLED("vidattr(%s)"), _traceattr(newmode)));
237
238         returnCode(vidputs(newmode, _nc_outch));
239 }
240
241 chtype termattrs(void)
242 {
243         chtype attrs = A_NORMAL;
244
245         if (enter_alt_charset_mode)
246                 attrs |= A_ALTCHARSET;
247
248         if (enter_blink_mode)
249                 attrs |= A_BLINK;
250
251         if (enter_bold_mode)
252                 attrs |= A_BOLD;
253
254         if (enter_dim_mode)
255                 attrs |= A_DIM;
256
257         if (enter_reverse_mode)
258                 attrs |= A_REVERSE;
259
260         if (enter_standout_mode)
261                 attrs |= A_STANDOUT;
262
263         if (enter_protected_mode)
264                 attrs |= A_PROTECT;
265
266         if (enter_secure_mode)
267                 attrs |= A_INVIS;
268
269         if (enter_underline_mode)
270                 attrs |= A_UNDERLINE;
271
272         if (SP->_coloron)
273                 attrs |= A_COLOR;
274
275         return(attrs);
276 }
277