1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 /*LINTLIBRARY*/
43
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #include "curses_inc.h"
47
48 #ifdef PC6300PLUS
49 #include <fcntl.h>
50 #include <sys/console.h>
51 #endif
52
53 #define NUM_OF_SPECIFIC_TURN_OFFS 3
54 extern chtype bit_attributes[];
55
56 int Oldcolors[] = { COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
57 COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE };
58
59 void
vidupdate(chtype newmode,chtype oldmode,int (* outc)(char))60 vidupdate(chtype newmode, chtype oldmode, int (*outc)(char))
61 {
62 bool color_terminal = (cur_term->_pairs_tbl) ? TRUE : FALSE;
63 chtype oldvideo = (oldmode & A_ATTRIBUTES) & ~A_COLOR;
64 chtype newvideo = (newmode & A_ATTRIBUTES) & ~A_COLOR;
65 int _change_video(chtype, chtype, int (*)(char));
66 void _change_color(short, int (*)(char));
67
68 /* if colors are used, extract the color related information from */
69 /* the old and new modes and then erase color-pairs fields in */
70 /* both arguments. */
71
72 if (color_terminal) {
73 /* LINTED */
74 short oldcolor = (short) PAIR_NUMBER(oldmode & A_COLOR);
75 /* LINTED */
76 short newcolor = (short) PAIR_NUMBER(newmode & A_COLOR);
77 chtype turn_off = A_COLOR;
78
79 /* erase information about video attributes that could not */
80 /* have been used with colors */
81
82 if (oldcolor == 0)
83 oldvideo &= ~turn_off;
84
85 if (no_color_video != -1)
86 turn_off |= (((chtype) no_color_video) << 16);
87
88 if (oldcolor != 0)
89 oldvideo &= ~turn_off;
90
91
92 /* if the new mode contains color information, then first */
93 /* deal with video attributes, and then with colors. This */
94 /* way color information will overwrite video information. */
95
96 if (newcolor != 0) {
97 /* erase information about video attributes that */
98 /* should not be used with colors */
99
100 newvideo &= ~turn_off;
101
102 /* if the new and the old video modes became */
103 /* the same don't bother with them */
104
105 if (newvideo != oldvideo) {
106 if ((_change_video(newvideo, oldvideo,
107 outc)) == -1) {
108 _Color_pair *cur_pair =
109 &cur_term->_cur_pair;
110 oldcolor = -1;
111 cur_pair->background =
112 cur_pair->foreground = -1;
113 }
114 }
115 if (newcolor != oldcolor)
116 _change_color(newcolor, outc);
117 }
118
119 /* new mode doesn't contain any color information. Deal */
120 /* with colors first (possibly turning of the colors that */
121 /* were contained in the oldmode, and then deal with video. */
122 /* This way video attributes will overwrite colors. */
123
124 else {
125 if (newcolor != oldcolor)
126 _change_color(newcolor, outc);
127 if (newvideo != oldvideo)
128 (void) _change_video(newvideo, oldvideo, outc);
129 }
130 } else
131 (void) _change_video(newvideo, oldvideo, outc);
132 }
133
134
135 int
_change_video(chtype newmode,chtype oldmode,int (* outc)(char))136 _change_video(chtype newmode, chtype oldmode, int (*outc)(char))
137 {
138 int rc = 0;
139
140 /* If you have set_attributes let the terminfo writer */
141 /* worry about it. */
142
143 if (!set_attributes) {
144 /*
145 * The trick is that we want to pre-process the new and oldmode
146 * so that we now know what they will really translate to on
147 * the physical screen.
148 * In the case where some attributes are being faked
149 * we get rid of the attributes being asked for and just have
150 * STANDOUT mode set. Therefore, if STANDOUT and UNDERLINE were
151 * on the screen but UNDERLINE was being faked to STANDOUT; and
152 * the new mode is just UNDERLINE, we will get rid of any faked
153 * modes and be left with and oldmode of STANDOUT and a new mode
154 * of STANDOUT, in which case the check for newmode and oldmode
155 * being equal will be true.
156 *
157 *
158 * This test is similar to the concept explained above.
159 * counter is the maximum attributes allowed on a terminal.
160 * For instance, on an hp/tvi950 without set_attributes
161 * the last video sequence sent will be the one the terminal
162 * will be in (on that spot). Therefore, in setupterm.c
163 * if ceol_standout_glitch or magic_cookie_glitch is set
164 * max_attributes is set to 1. This is because on those terminals
165 * only one attribute can be on at once. So, we pre-process the
166 * oldmode and the newmode and only leave the bits that are
167 * significant. In other words, if on an hp you ask for STANDOUT
168 * and UNDERLINE it will become only STANDOUT since that is the
169 * first bit that is looked at. If then the user goes from
170 * STANDOUT and UNDERLINE to STANDOUT and REVERSE the oldmode will
171 * become STANDOUT and the newmode will become STANDOUT.
172 *
173 * This also helps the code below in that on a hp or tvi950 only
174 * one bit will ever be set so that no code has to be added to
175 * cut out early in case two attributes were asked for.
176 */
177
178 chtype check_faked, modes[2];
179 int counter = max_attributes, i, j, tempmode;
180 int k = (cur_term->sgr_mode == oldmode) ? 1 : 2;
181
182 modes[0] = newmode;
183 modes[1] = oldmode;
184
185 while (k-- > 0) {
186 if ((check_faked = (modes[k] &
187 cur_term->sgr_faked)) != A_NORMAL) {
188 modes[k] &= ~check_faked;
189 modes[k] |= A_STANDOUT;
190 }
191
192 if ((j = counter) >= 0) {
193 tempmode = A_NORMAL;
194 if (j > 0) {
195 for (i = 0; i < NUM_ATTRIBUTES; i++) {
196 if (modes[k] &
197 bit_attributes[i]) {
198 tempmode |=
199 bit_attributes[i];
200 if (--j == 0)
201 break;
202 }
203 }
204 }
205 modes[k] = tempmode;
206 }
207 }
208 newmode = modes[0];
209 oldmode = modes[1];
210 }
211
212 if (newmode == oldmode)
213 return (rc);
214
215 #ifdef DEBUG
216 if (outf)
217 fprintf(outf, "vidupdate oldmode=%o, newmode=%o\n",
218 oldmode, newmode);
219 #endif
220
221 if (set_attributes) {
222 (void) tputs(tparm(set_attributes,
223 newmode & A_STANDOUT,
224 newmode & A_UNDERLINE,
225 newmode & A_REVERSE,
226 newmode & A_BLINK,
227 newmode & A_DIM,
228 newmode & A_BOLD,
229 newmode & A_INVIS,
230 newmode & A_PROTECT,
231 newmode & A_ALTCHARSET),
232 1, outc);
233 rc = -1;
234 } else {
235 chtype turn_on, turn_off;
236 int i;
237
238 /*
239 * If we are going to turn something on anyway and we are
240 * on a glitchy terminal, don't bother turning it off
241 * since by turning something on you turn everything else off.
242 */
243
244 if ((ceol_standout_glitch || magic_cookie_glitch >= 0) &&
245 ((turn_on = ((oldmode ^ newmode) & newmode)) !=
246 A_NORMAL)) {
247 goto turn_on_code;
248 }
249
250 if ((turn_off = (oldmode & newmode) ^ oldmode) != A_NORMAL) {
251 /*
252 * Check for things to turn off.
253 * First see if we are going to turn off something
254 * that doesn't have a specific turn off capability.
255 *
256 * Then check to see if, even though there may be a specific
257 * turn off sequence, this terminal doesn't have one or
258 * the turn off sequence also turns off something else.
259 */
260 if ((turn_off & ~(A_ALTCHARSET | A_STANDOUT | A_UNDERLINE)) ||
261 (turn_off != (turn_off & cur_term->check_turn_off))) {
262 (void) tputs(tparm_p0(exit_attribute_mode), 1, outc);
263 rc = -1;
264 oldmode = A_NORMAL;
265 } else {
266 for (i = 0; i < NUM_OF_SPECIFIC_TURN_OFFS; i++) {
267 if (turn_off & bit_attributes[i]) {
268 (void) tputs(tparm_p0
269 (cur_term->turn_off_seq[i]),
270 1, outc);
271 oldmode &= ~bit_attributes[i];
272 rc = -1;
273 }
274 }
275 }
276 }
277
278 if ((turn_on = ((oldmode ^ newmode) & newmode)) != A_NORMAL) {
279 turn_on_code:
280
281 /* Check for modes to turn on. */
282
283 for (i = 0; i < NUM_ATTRIBUTES; i++)
284 if (turn_on & bit_attributes[i]) {
285 (void) tputs(tparm_p0(cur_term->turn_on_seq[i]),
286 1, outc);
287 rc = -1;
288 /*
289 * Keep turning off the bit(s) that we just
290 * sent to the screen. As soon as turn_on
291 * reaches A_NORMAL we don't have to turn
292 * anything else on and we can
293 * break out of the loop.
294 */
295 if ((turn_on &= ~bit_attributes[i]) ==
296 A_NORMAL)
297 break;
298 }
299 }
300
301 if (magic_cookie_glitch > 0)
302 (void) tputs(cursor_left, 1, outc);
303 }
304 cur_term->sgr_mode = newmode;
305 return (rc);
306 }
307
308
309 void
_change_color(short newcolor,int (* outc)(char))310 _change_color(short newcolor, int (*outc)(char))
311 {
312 #ifndef PC6300PLUS
313 {
314 _Color_pair *ptp = cur_term->_pairs_tbl;
315 /* pairs table pointer */
316 _Color_pair *cur_pair = &cur_term->_cur_pair;
317
318 /* MORE: we may have to change some stuff, depending on whether */
319 /* HP terminals will be changing the background, or not */
320
321 if (newcolor == 0) {
322 if (orig_pair)
323 (void) tputs(tparm_p0(orig_pair), 1, outc);
324 if (set_a_background || set_a_foreground ||
325 set_background || set_foreground) {
326 cur_pair->background = -1;
327 cur_pair->foreground = -1;
328 }
329 return;
330 }
331
332 /* if we are on HP type terminal, just send an escape sequence */
333 /* to use desired color pair (we could have done some optimization: */
334 /* check if both the foreground and background of newcolor match */
335 /* the ones of cur_term->_cur_pair. but that will happen only when */
336 /* two color pairs are defined exacly the same, and probably not */
337 /* worth the effort). */
338
339 if (set_color_pair)
340 (void) tputs(tparm_p1(set_color_pair, newcolor), 1, outc);
341
342 /* on Tek model we can do some optimization. */
343
344 else {
345 if (ptp[newcolor].background != cur_pair->background) {
346 if (set_a_background)
347 (void) tputs(tparm_p1(set_a_background,
348 ptp[newcolor].background), 1, outc);
349 else if (set_background)
350 (void) tputs(tparm_p1(set_background,
351 Oldcolors[ptp[newcolor].background]),
352 1, outc);
353 cur_pair->background = ptp[newcolor].background;
354 }
355 if (ptp[newcolor].foreground != cur_pair->foreground) {
356 if (set_a_foreground)
357 (void) tputs(tparm_p1(set_a_foreground,
358 ptp[newcolor].foreground), 1, outc);
359 else if (set_foreground)
360 (void) tputs(tparm_p1(set_foreground,
361 Oldcolors[ptp[newcolor].foreground]),
362 1, outc);
363 cur_pair->foreground = ptp[newcolor].foreground;
364 }
365 }
366 }
367 #else
368 {
369 /* the following code is for PC6300 PLUS: it uses BOLD terminfo */
370 /* entry for turning on colors, and SGR0 for turning them off. */
371 /* Every time a new color-pair is used, we are forced to do an */
372 /* ioctl read, and the send 'enter_bold_mode' escape sequence. */
373 /* This could be improved by using */
374 /* DIM, UNDERLINE, and REVERSE in addition to BOLD */
375
376 struct console con;
377 _Color_pair *ptp = cur_term->_pairs_tbl;
378 /* pairs table pointer */
379 back = ptp[newcolor].background;
380 fore = ptp[newcolor].foreground;
381
382 (void) fflush(SP->term_file);
383 ioctl(cur_term->Filedes, CONIOGETDATA, &con);
384 #define BOLD 4
385 con.l[con.page].colors[BOLD] =
386 ((back + back + (fore > 5)) * 8 + fore) & 0177;
387 ioctl(cur_term->Filedes, CONIOSETDATA, &con);
388 (void) tputs(enter_bold_mode, 1, outc);
389 }
390 #endif
391 }
392