150276Speter/**************************************************************************** 2174993Srafan * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996 on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * vidputs(newmode, outc) 3750276Speter * 3850276Speter * newmode is taken to be the logical 'or' of the symbols in curses.h 3950276Speter * representing graphic renditions. The terminal is set to be in all of 4050276Speter * the given modes, if possible. 4150276Speter * 4250276Speter * if the new attribute is normal 4350276Speter * if exit-alt-char-set exists 4450276Speter * emit it 4550276Speter * emit exit-attribute-mode 4650276Speter * else if set-attributes exists 4750276Speter * use it to set exactly what you want 4850276Speter * else 4950276Speter * if exit-attribute-mode exists 5050276Speter * turn off everything 5150276Speter * else 5250276Speter * turn off those which can be turned off and aren't in 5350276Speter * newmode. 5450276Speter * turn on each mode which should be on and isn't, one by one 5550276Speter * 5650276Speter * NOTE that this algorithm won't achieve the desired mix of attributes 5750276Speter * in some cases, but those are probably just those cases in which it is 5850276Speter * actually impossible, anyway, so... 5950276Speter * 6050276Speter * NOTE that we cannot assume that there's no interaction between color 6150276Speter * and other attribute resets. So each time we reset color (or other 6250276Speter * attributes) we'll have to be prepared to restore the other. 6350276Speter */ 6450276Speter 6550276Speter#include <curses.priv.h> 6650276Speter#include <term.h> 6750276Speter 68174993SrafanMODULE_ID("$Id: lib_vidattr.c,v 1.49 2007/06/30 21:58:04 tom Exp $") 6950276Speter 7050276Speter#define doPut(mode) TPUTS_TRACE(#mode); tputs(mode, 1, outc) 7150276Speter 7250276Speter#define TurnOn(mask,mode) \ 7350276Speter if ((turn_on & mask) && mode) { doPut(mode); } 7450276Speter 7550276Speter#define TurnOff(mask,mode) \ 7650276Speter if ((turn_off & mask) && mode) { doPut(mode); turn_off &= ~mask; } 7750276Speter 7850276Speter /* if there is no current screen, assume we *can* do color */ 7950276Speter#define SetColorsIf(why,old_attr) \ 8062449Speter if (can_color && (why)) { \ 8150276Speter int old_pair = PAIR_NUMBER(old_attr); \ 8266963Speter TR(TRACE_ATTRS, ("old pair = %d -- new pair = %d", old_pair, pair)); \ 8350276Speter if ((pair != old_pair) \ 8462449Speter || (fix_pair0 && (pair == 0)) \ 8550276Speter || (reverse ^ ((old_attr & A_REVERSE) != 0))) { \ 8662449Speter _nc_do_color(old_pair, pair, reverse, outc); \ 8750276Speter } \ 8850276Speter } 8950276Speter 90174993Srafan#define PreviousAttr _nc_prescreen.previous_attr 91174993Srafan 9276726SpeterNCURSES_EXPORT(int) 93166124Srafanvidputs(chtype newmode, int (*outc) (int)) 9450276Speter{ 9562449Speter attr_t turn_on, turn_off; 9662449Speter int pair; 9762449Speter bool reverse = FALSE; 9862449Speter bool can_color = (SP == 0 || SP->_coloron); 9966963Speter#if NCURSES_EXT_FUNCS 10062449Speter bool fix_pair0 = (SP != 0 && SP->_coloron && !SP->_default_color); 10162449Speter#else 10262449Speter#define fix_pair0 FALSE 10362449Speter#endif 10450276Speter 105174993Srafan newmode &= A_ATTRIBUTES; 10662449Speter T((T_CALLED("vidputs(%s)"), _traceattr(newmode))); 10750276Speter 10862449Speter /* this allows us to go on whether or not newterm() has been called */ 10962449Speter if (SP) 110174993Srafan PreviousAttr = AttrOf(SCREEN_ATTRS(SP)); 11150276Speter 112174993Srafan TR(TRACE_ATTRS, ("previous attribute was %s", _traceattr(PreviousAttr))); 11350276Speter 11462449Speter if ((SP != 0) 115166124Srafan && (magic_cookie_glitch > 0)) { 116166124Srafan#if USE_XMC_SUPPORT 117174993Srafan static const chtype table[] = 118166124Srafan { 119166124Srafan A_STANDOUT, 120166124Srafan A_UNDERLINE, 121166124Srafan A_REVERSE, 122166124Srafan A_BLINK, 123166124Srafan A_DIM, 124166124Srafan A_BOLD, 125166124Srafan A_INVIS, 126166124Srafan A_PROTECT, 127166124Srafan }; 128166124Srafan unsigned n; 129166124Srafan int used = 0; 130166124Srafan int limit = (max_attributes <= 0) ? 1 : max_attributes; 131166124Srafan chtype retain = 0; 132166124Srafan 133166124Srafan /* 134166124Srafan * Limit the number of attribute bits set in the newmode according to 135166124Srafan * the terminfo max_attributes value. 136166124Srafan */ 137166124Srafan for (n = 0; n < SIZEOF(table); ++n) { 138166124Srafan if ((table[n] & SP->_ok_attributes) == 0) { 139166124Srafan newmode &= ~table[n]; 140166124Srafan } else if ((table[n] & newmode) != 0) { 141166124Srafan if (used++ >= limit) { 142166124Srafan newmode &= ~table[n]; 143166124Srafan if (newmode == retain) 144166124Srafan break; 145166124Srafan } else { 146166124Srafan retain = newmode; 147166124Srafan } 148166124Srafan } 149166124Srafan } 150166124Srafan#else 15162449Speter newmode &= ~(SP->_xmc_suppress); 15250276Speter#endif 153166124Srafan TR(TRACE_ATTRS, ("suppressed attribute is %s", _traceattr(newmode))); 154166124Srafan } 15550276Speter 15662449Speter /* 15762449Speter * If we have a terminal that cannot combine color with video 15862449Speter * attributes, use the colors in preference. 15962449Speter */ 16062449Speter if (((newmode & A_COLOR) != 0 16166963Speter || fix_pair0) 16262449Speter && (no_color_video > 0)) { 16366963Speter /* 16466963Speter * If we had chosen the A_xxx definitions to correspond to the 16566963Speter * no_color_video mask, we could simply shift it up and mask off the 16666963Speter * attributes. But we did not (actually copied Solaris' definitions). 16766963Speter * However, this is still simpler/faster than a lookup table. 16866963Speter * 16966963Speter * The 63 corresponds to A_STANDOUT, A_UNDERLINE, A_REVERSE, A_BLINK, 17066963Speter * A_DIM, A_BOLD which are 1:1 with no_color_video. The bits that 17166963Speter * correspond to A_INVIS, A_PROTECT (192) must be shifted up 1 and 17266963Speter * A_ALTCHARSET (256) down 2 to line up. We use the NCURSES_BITS 17366963Speter * macro so this will work properly for the wide-character layout. 17466963Speter */ 17576726Speter unsigned value = no_color_video; 17676726Speter attr_t mask = NCURSES_BITS((value & 63) 17776726Speter | ((value & 192) << 1) 17876726Speter | ((value & 256) >> 2), 8); 17962449Speter 18076726Speter if ((mask & A_REVERSE) != 0 18176726Speter && (newmode & A_REVERSE) != 0) { 18266963Speter reverse = TRUE; 18366963Speter mask &= ~A_REVERSE; 18450276Speter } 18566963Speter newmode &= ~mask; 18662449Speter } 18750276Speter 188174993Srafan if (newmode == PreviousAttr) 18962449Speter returnCode(OK); 19050276Speter 19162449Speter pair = PAIR_NUMBER(newmode); 19250276Speter 19362449Speter if (reverse) { 19462449Speter newmode &= ~A_REVERSE; 19562449Speter } 19650276Speter 197174993Srafan turn_off = (~newmode & PreviousAttr) & ALL_BUT_COLOR; 198174993Srafan turn_on = (newmode & ~PreviousAttr) & ALL_BUT_COLOR; 19950276Speter 200174993Srafan SetColorsIf(((pair == 0) && !fix_pair0), PreviousAttr); 20150276Speter 20262449Speter if (newmode == A_NORMAL) { 203174993Srafan if ((PreviousAttr & A_ALTCHARSET) && exit_alt_charset_mode) { 20462449Speter doPut(exit_alt_charset_mode); 205174993Srafan PreviousAttr &= ~A_ALTCHARSET; 20662449Speter } 207174993Srafan if (PreviousAttr) { 20866963Speter if (exit_attribute_mode) { 20966963Speter doPut(exit_attribute_mode); 21066963Speter } else { 21166963Speter if (!SP || SP->_use_rmul) { 21266963Speter TurnOff(A_UNDERLINE, exit_underline_mode); 21366963Speter } 21466963Speter if (!SP || SP->_use_rmso) { 21566963Speter TurnOff(A_STANDOUT, exit_standout_mode); 21666963Speter } 21766963Speter } 218174993Srafan PreviousAttr &= ALL_BUT_COLOR; 21962449Speter } 22050276Speter 221174993Srafan SetColorsIf((pair != 0) || fix_pair0, PreviousAttr); 22297049Speter } else if (set_attributes) { 22362449Speter if (turn_on || turn_off) { 22462449Speter TPUTS_TRACE("set_attributes"); 22562449Speter tputs(tparm(set_attributes, 22666963Speter (newmode & A_STANDOUT) != 0, 22766963Speter (newmode & A_UNDERLINE) != 0, 22866963Speter (newmode & A_REVERSE) != 0, 22966963Speter (newmode & A_BLINK) != 0, 23066963Speter (newmode & A_DIM) != 0, 23166963Speter (newmode & A_BOLD) != 0, 23266963Speter (newmode & A_INVIS) != 0, 23366963Speter (newmode & A_PROTECT) != 0, 23466963Speter (newmode & A_ALTCHARSET) != 0), 1, outc); 235174993Srafan PreviousAttr &= ALL_BUT_COLOR; 23662449Speter } 237174993Srafan SetColorsIf((pair != 0) || fix_pair0, PreviousAttr); 23862449Speter } else { 23950276Speter 24066963Speter TR(TRACE_ATTRS, ("turning %s off", _traceattr(turn_off))); 24150276Speter 24262449Speter TurnOff(A_ALTCHARSET, exit_alt_charset_mode); 24350276Speter 24462449Speter if (!SP || SP->_use_rmul) { 24562449Speter TurnOff(A_UNDERLINE, exit_underline_mode); 24662449Speter } 24750276Speter 24862449Speter if (!SP || SP->_use_rmso) { 24962449Speter TurnOff(A_STANDOUT, exit_standout_mode); 25062449Speter } 25150276Speter 25262449Speter if (turn_off && exit_attribute_mode) { 25362449Speter doPut(exit_attribute_mode); 254166124Srafan turn_on |= (newmode & ALL_BUT_COLOR); 255174993Srafan PreviousAttr &= ALL_BUT_COLOR; 25662449Speter } 257174993Srafan SetColorsIf((pair != 0) || fix_pair0, PreviousAttr); 25850276Speter 25966963Speter TR(TRACE_ATTRS, ("turning %s on", _traceattr(turn_on))); 26062449Speter /* *INDENT-OFF* */ 26162449Speter TurnOn(A_ALTCHARSET, enter_alt_charset_mode); 26262449Speter TurnOn(A_BLINK, enter_blink_mode); 26362449Speter TurnOn(A_BOLD, enter_bold_mode); 26462449Speter TurnOn(A_DIM, enter_dim_mode); 26562449Speter TurnOn(A_REVERSE, enter_reverse_mode); 26662449Speter TurnOn(A_STANDOUT, enter_standout_mode); 26762449Speter TurnOn(A_PROTECT, enter_protected_mode); 26862449Speter TurnOn(A_INVIS, enter_secure_mode); 26962449Speter TurnOn(A_UNDERLINE, enter_underline_mode); 270166124Srafan#if USE_WIDEC_SUPPORT 27162449Speter TurnOn(A_HORIZONTAL, enter_horizontal_hl_mode); 27262449Speter TurnOn(A_LEFT, enter_left_hl_mode); 27362449Speter TurnOn(A_LOW, enter_low_hl_mode); 27462449Speter TurnOn(A_RIGHT, enter_right_hl_mode); 27562449Speter TurnOn(A_TOP, enter_top_hl_mode); 27662449Speter TurnOn(A_VERTICAL, enter_vertical_hl_mode); 27797049Speter#endif 27862449Speter /* *INDENT-ON* */ 27950276Speter 28062449Speter } 28150276Speter 28262449Speter if (reverse) 28362449Speter newmode |= A_REVERSE; 28450276Speter 28562449Speter if (SP) 286166124Srafan SetAttr(SCREEN_ATTRS(SP), newmode); 28762449Speter else 288174993Srafan PreviousAttr = newmode; 28950276Speter 29062449Speter returnCode(OK); 29150276Speter} 29250276Speter 29376726SpeterNCURSES_EXPORT(int) 29497049Spetervidattr(chtype newmode) 29550276Speter{ 29662449Speter T((T_CALLED("vidattr(%s)"), _traceattr(newmode))); 29750276Speter 29862449Speter returnCode(vidputs(newmode, _nc_outch)); 29950276Speter} 30050276Speter 30176726SpeterNCURSES_EXPORT(chtype) 30262449Spetertermattrs(void) 30350276Speter{ 30462449Speter chtype attrs = A_NORMAL; 30550276Speter 30666963Speter T((T_CALLED("termattrs()"))); 30762449Speter if (enter_alt_charset_mode) 30862449Speter attrs |= A_ALTCHARSET; 30950276Speter 31062449Speter if (enter_blink_mode) 31162449Speter attrs |= A_BLINK; 31250276Speter 31362449Speter if (enter_bold_mode) 31462449Speter attrs |= A_BOLD; 31550276Speter 31662449Speter if (enter_dim_mode) 31762449Speter attrs |= A_DIM; 31850276Speter 31962449Speter if (enter_reverse_mode) 32062449Speter attrs |= A_REVERSE; 32150276Speter 32262449Speter if (enter_standout_mode) 32362449Speter attrs |= A_STANDOUT; 32450276Speter 32562449Speter if (enter_protected_mode) 32662449Speter attrs |= A_PROTECT; 32750276Speter 32862449Speter if (enter_secure_mode) 32962449Speter attrs |= A_INVIS; 33050276Speter 33162449Speter if (enter_underline_mode) 33262449Speter attrs |= A_UNDERLINE; 33350276Speter 33462449Speter if (SP->_coloron) 33562449Speter attrs |= A_COLOR; 33650276Speter 33766963Speter returnChar(attrs); 33850276Speter} 339