diff options
Diffstat (limited to 'usr/src/lib/libcurses/screen/vidupdate.c')
-rw-r--r-- | usr/src/lib/libcurses/screen/vidupdate.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/usr/src/lib/libcurses/screen/vidupdate.c b/usr/src/lib/libcurses/screen/vidupdate.c new file mode 100644 index 0000000000..48177f581d --- /dev/null +++ b/usr/src/lib/libcurses/screen/vidupdate.c @@ -0,0 +1,391 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1997 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1988 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/*LINTLIBRARY*/ + +#include <sys/types.h> +#include <stdlib.h> +#include "curses_inc.h" + +#ifdef PC6300PLUS +#include <fcntl.h> +#include <sys/console.h> +#endif + +#define NUM_OF_SPECIFIC_TURN_OFFS 3 +extern chtype bit_attributes[]; + +int Oldcolors[] = { COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, + COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE }; + +void +vidupdate(chtype newmode, chtype oldmode, int (*outc)(char)) +{ + bool color_terminal = (cur_term->_pairs_tbl) ? TRUE : FALSE; + chtype oldvideo = (oldmode & A_ATTRIBUTES) & ~A_COLOR; + chtype newvideo = (newmode & A_ATTRIBUTES) & ~A_COLOR; + int _change_video(chtype, chtype, int (*)(char)); + void _change_color(short, int (*)(char)); + + /* if colors are used, extract the color related information from */ + /* the old and new modes and then erase color-pairs fields in */ + /* both arguments. */ + + if (color_terminal) { + /* LINTED */ + short oldcolor = (short) PAIR_NUMBER(oldmode & A_COLOR); + /* LINTED */ + short newcolor = (short) PAIR_NUMBER(newmode & A_COLOR); + chtype turn_off = A_COLOR; + + /* erase information about video attributes that could not */ + /* have been used with colors */ + + if (oldcolor == 0) + oldvideo &= ~turn_off; + + if (no_color_video != -1) + turn_off |= (((chtype) no_color_video) << 16); + + if (oldcolor != 0) + oldvideo &= ~turn_off; + + + /* if the new mode contains color information, then first */ + /* deal with video attributes, and then with colors. This */ + /* way color information will overwrite video information. */ + + if (newcolor != 0) { + /* erase information about video attributes that */ + /* should not be used with colors */ + + newvideo &= ~turn_off; + + /* if the new and the old video modes became */ + /* the same don't bother with them */ + + if (newvideo != oldvideo) { + if ((_change_video(newvideo, oldvideo, + outc)) == -1) { + _Color_pair *cur_pair = + &cur_term->_cur_pair; + oldcolor = -1; + cur_pair->background = + cur_pair->foreground = -1; + } + } + if (newcolor != oldcolor) + _change_color(newcolor, outc); + } + + /* new mode doesn't contain any color information. Deal */ + /* with colors first (possibly turning of the colors that */ + /* were contained in the oldmode, and then deal with video. */ + /* This way video attributes will overwrite colors. */ + + else { + if (newcolor != oldcolor) + _change_color(newcolor, outc); + if (newvideo != oldvideo) + (void) _change_video(newvideo, oldvideo, outc); + } + } else + (void) _change_video(newvideo, oldvideo, outc); +} + + +int +_change_video(chtype newmode, chtype oldmode, int (*outc)(char)) +{ + int rc = 0; + + /* If you have set_attributes let the terminfo writer */ + /* worry about it. */ + + if (!set_attributes) { + /* + * The trick is that we want to pre-process the new and oldmode + * so that we now know what they will really translate to on + * the physical screen. + * In the case where some attributes are being faked + * we get rid of the attributes being asked for and just have + * STANDOUT mode set. Therefore, if STANDOUT and UNDERLINE were + * on the screen but UNDERLINE was being faked to STANDOUT; and + * the new mode is just UNDERLINE, we will get rid of any faked + * modes and be left with and oldmode of STANDOUT and a new mode + * of STANDOUT, in which case the check for newmode and oldmode + * being equal will be true. + * + * + * This test is similar to the concept explained above. + * counter is the maximum attributes allowed on a terminal. + * For instance, on an hp/tvi950 without set_attributes + * the last video sequence sent will be the one the terminal + * will be in (on that spot). Therefore, in setupterm.c + * if ceol_standout_glitch or magic_cookie_glitch is set + * max_attributes is set to 1. This is because on those terminals + * only one attribute can be on at once. So, we pre-process the + * oldmode and the newmode and only leave the bits that are + * significant. In other words, if on an hp you ask for STANDOUT + * and UNDERLINE it will become only STANDOUT since that is the + * first bit that is looked at. If then the user goes from + * STANDOUT and UNDERLINE to STANDOUT and REVERSE the oldmode will + * become STANDOUT and the newmode will become STANDOUT. + * + * This also helps the code below in that on a hp or tvi950 only + * one bit will ever be set so that no code has to be added to + * cut out early in case two attributes were asked for. + */ + + chtype check_faked, modes[2]; + int counter = max_attributes, i, j, tempmode; + int k = (cur_term->sgr_mode == oldmode) ? 1 : 2; + + modes[0] = newmode; + modes[1] = oldmode; + + while (k-- > 0) { + if ((check_faked = (modes[k] & + cur_term->sgr_faked)) != A_NORMAL) { + modes[k] &= ~check_faked; + modes[k] |= A_STANDOUT; + } + + if ((j = counter) >= 0) { + tempmode = A_NORMAL; + if (j > 0) { + for (i = 0; i < NUM_ATTRIBUTES; i++) { + if (modes[k] & + bit_attributes[i]) { + tempmode |= + bit_attributes[i]; + if (--j == 0) + break; + } + } + } + modes[k] = tempmode; + } + } + newmode = modes[0]; + oldmode = modes[1]; + } + + if (newmode == oldmode) + return (rc); + +#ifdef DEBUG + if (outf) + fprintf(outf, "vidupdate oldmode=%o, newmode=%o\n", + oldmode, newmode); +#endif + + if (set_attributes) { + (void) tputs(tparm(set_attributes, + newmode & A_STANDOUT, + newmode & A_UNDERLINE, + newmode & A_REVERSE, + newmode & A_BLINK, + newmode & A_DIM, + newmode & A_BOLD, + newmode & A_INVIS, + newmode & A_PROTECT, + newmode & A_ALTCHARSET), + 1, outc); + rc = -1; + } else { + chtype turn_on, turn_off; + int i; + + /* + * If we are going to turn something on anyway and we are + * on a glitchy terminal, don't bother turning it off + * since by turning something on you turn everything else off. + */ + + if ((ceol_standout_glitch || magic_cookie_glitch >= 0) && + ((turn_on = ((oldmode ^ newmode) & newmode)) != + A_NORMAL)) { + goto turn_on_code; + } + + if ((turn_off = (oldmode & newmode) ^ oldmode) != A_NORMAL) { + /* + * Check for things to turn off. + * First see if we are going to turn off something + * that doesn't have a specific turn off capability. + * + * Then check to see if, even though there may be a specific + * turn off sequence, this terminal doesn't have one or + * the turn off sequence also turns off something else. + */ + if ((turn_off & ~(A_ALTCHARSET | A_STANDOUT | A_UNDERLINE)) || + (turn_off != (turn_off & cur_term->check_turn_off))) { + (void) tputs(tparm_p0(exit_attribute_mode), 1, outc); + rc = -1; + oldmode = A_NORMAL; + } else { + for (i = 0; i < NUM_OF_SPECIFIC_TURN_OFFS; i++) { + if (turn_off & bit_attributes[i]) { + (void) tputs(tparm_p0 + (cur_term->turn_off_seq[i]), + 1, outc); + oldmode &= ~bit_attributes[i]; + rc = -1; + } + } + } + } + + if ((turn_on = ((oldmode ^ newmode) & newmode)) != A_NORMAL) { +turn_on_code: + + /* Check for modes to turn on. */ + + for (i = 0; i < NUM_ATTRIBUTES; i++) + if (turn_on & bit_attributes[i]) { + (void) tputs(tparm_p0(cur_term->turn_on_seq[i]), + 1, outc); + rc = -1; + /* + * Keep turning off the bit(s) that we just + * sent to the screen. As soon as turn_on + * reaches A_NORMAL we don't have to turn + * anything else on and we can + * break out of the loop. + */ + if ((turn_on &= ~bit_attributes[i]) == + A_NORMAL) + break; + } + } + + if (magic_cookie_glitch > 0) + (void) tputs(cursor_left, 1, outc); + } + cur_term->sgr_mode = newmode; + return (rc); +} + + +void +_change_color(short newcolor, int (*outc)(char)) +{ +#ifndef PC6300PLUS + { + _Color_pair *ptp = cur_term->_pairs_tbl; + /* pairs table pointer */ + _Color_pair *cur_pair = &cur_term->_cur_pair; + + /* MORE: we may have to change some stuff, depending on whether */ + /* HP terminals will be changing the background, or not */ + + if (newcolor == 0) { + if (orig_pair) + (void) tputs(tparm_p0(orig_pair), 1, outc); + if (set_a_background || set_a_foreground || + set_background || set_foreground) { + cur_pair->background = -1; + cur_pair->foreground = -1; + } + return; + } + + /* if we are on HP type terminal, just send an escape sequence */ + /* to use desired color pair (we could have done some optimization: */ + /* check if both the foreground and background of newcolor match */ + /* the ones of cur_term->_cur_pair. but that will happen only when */ + /* two color pairs are defined exacly the same, and probably not */ + /* worth the effort). */ + + if (set_color_pair) + (void) tputs(tparm_p1(set_color_pair, newcolor), 1, outc); + + /* on Tek model we can do some optimization. */ + + else { + if (ptp[newcolor].background != cur_pair->background) { + if (set_a_background) + (void) tputs(tparm_p1(set_a_background, + ptp[newcolor].background), 1, outc); + else if (set_background) + (void) tputs(tparm_p1(set_background, + Oldcolors[ptp[newcolor].background]), + 1, outc); + cur_pair->background = ptp[newcolor].background; + } + if (ptp[newcolor].foreground != cur_pair->foreground) { + if (set_a_foreground) + (void) tputs(tparm_p1(set_a_foreground, + ptp[newcolor].foreground), 1, outc); + else if (set_foreground) + (void) tputs(tparm_p1(set_foreground, + Oldcolors[ptp[newcolor].foreground]), + 1, outc); + cur_pair->foreground = ptp[newcolor].foreground; + } + } + } +#else + { + /* the following code is for PC6300 PLUS: it uses BOLD terminfo */ + /* entry for turning on colors, and SGR0 for turning them off. */ + /* Every time a new color-pair is used, we are forced to do an */ + /* ioctl read, and the send 'enter_bold_mode' escape sequence. */ + /* This could be improved by using */ + /* DIM, UNDERLINE, and REVERSE in addition to BOLD */ + + struct console con; + _Color_pair *ptp = cur_term->_pairs_tbl; + /* pairs table pointer */ + back = ptp[newcolor].background; + fore = ptp[newcolor].foreground; + + (void) fflush(SP->term_file); + ioctl(cur_term->Filedes, CONIOGETDATA, &con); +#define BOLD 4 + con.l[con.page].colors[BOLD] = + ((back + back + (fore > 5)) * 8 + fore) & 0177; + ioctl(cur_term->Filedes, CONIOSETDATA, &con); + (void) tputs(enter_bold_mode, 1, outc); + } +#endif +} |