Home | History | Annotate | Line # | Download | only in libcurses
color.c revision 1.29
      1 /*	$NetBSD: color.c,v 1.29 2004/03/22 18:57:38 jdc Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Julian Coleman.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 #ifndef lint
     41 __RCSID("$NetBSD: color.c,v 1.29 2004/03/22 18:57:38 jdc Exp $");
     42 #endif				/* not lint */
     43 
     44 #include "curses.h"
     45 #include "curses_private.h"
     46 
     47 /* Have we initialised colours? */
     48 int	__using_color = 0;
     49 
     50 /* Default colour number */
     51 attr_t	__default_color = 0;
     52 
     53 /* Default colour pair values - white on black. */
     54 struct __pair	__default_pair = {COLOR_WHITE, COLOR_BLACK, 0};
     55 
     56 /* Default colour values */
     57 /* Flags for colours and pairs */
     58 #define	__USED		0x01
     59 
     60 static void
     61 __change_pair(short);
     62 
     63 /*
     64  * has_colors --
     65  *	Check if terminal has colours.
     66  */
     67 bool
     68 has_colors(void)
     69 {
     70 	if (__tc_Co > 0 && __tc_pa > 0 && ((__tc_AF != NULL &&
     71 	    __tc_AB != NULL) || __tc_Ip != NULL || __tc_Ic != NULL ||
     72 	    (__tc_Sb != NULL && __tc_Sf != NULL)))
     73 		return(TRUE);
     74 	else
     75 		return(FALSE);
     76 }
     77 
     78 /*
     79  * can_change_color --
     80  *	Check if terminal can change colours.
     81  */
     82 bool
     83 can_change_color(void)
     84 {
     85 	if (__tc_cc)
     86 		return(TRUE);
     87 	else
     88 		return(FALSE);
     89 }
     90 
     91 /*
     92  * start_color --
     93  *	Initialise colour support.
     94  */
     95 int
     96 start_color(void)
     97 {
     98 	int			 i;
     99 	attr_t			 temp_nc;
    100 	struct __winlist	*wlp;
    101 	WINDOW			*win;
    102 	int			 y, x;
    103 
    104 	if (has_colors() == FALSE)
    105 		return(ERR);
    106 
    107 	/* Max colours and colour pairs */
    108 	if (__tc_Co == -1)
    109 		COLORS = 0;
    110 	else {
    111 		COLORS = __tc_Co > MAX_COLORS ? MAX_COLORS : __tc_Co;
    112 		if (__tc_pa == -1) {
    113 			COLOR_PAIRS = 0;
    114 			COLORS = 0;
    115 		} else {
    116 			COLOR_PAIRS = (__tc_pa > MAX_PAIRS - 1 ?
    117 			    MAX_PAIRS - 1 : __tc_pa);
    118 			 /* Use the last colour pair for curses default. */
    119 			__default_color = COLOR_PAIR(MAX_PAIRS - 1);
    120 		}
    121 	}
    122 	if (!COLORS)
    123 		return (ERR);
    124 
    125 	_cursesi_screen->COLORS = COLORS;
    126 	_cursesi_screen->COLOR_PAIRS = COLOR_PAIRS;
    127 
    128 	/* Reset terminal colour and colour pairs. */
    129 	if (__tc_oc != NULL)
    130 		tputs(__tc_oc, 0, __cputchar);
    131 	if (__tc_op != NULL) {
    132 		tputs(__tc_op, 0, __cputchar);
    133 		curscr->wattr &= _cursesi_screen->mask_op;
    134 	}
    135 
    136 	/* Type of colour manipulation - ANSI/TEK/HP/other */
    137 	if (__tc_AF != NULL && __tc_AB != NULL)
    138 		_cursesi_screen->color_type = COLOR_ANSI;
    139 	else if (__tc_Ip != NULL)
    140 		_cursesi_screen->color_type = COLOR_HP;
    141 	else if (__tc_Ic != NULL)
    142 		_cursesi_screen->color_type = COLOR_TEK;
    143 	else if (__tc_Sb != NULL && __tc_Sf != NULL)
    144 		_cursesi_screen->color_type = COLOR_OTHER;
    145 	else
    146 		return(ERR);		/* Unsupported colour method */
    147 
    148 #ifdef DEBUG
    149 	__CTRACE("start_color: COLORS = %d, COLOR_PAIRS = %d",
    150 	    COLORS, COLOR_PAIRS);
    151 	switch (_cursesi_screen->color_type) {
    152 	case COLOR_ANSI:
    153 		__CTRACE(" (ANSI style)\n");
    154 		break;
    155 	case COLOR_HP:
    156 		__CTRACE(" (HP style)\n");
    157 		break;
    158 	case COLOR_TEK:
    159 		__CTRACE(" (Tektronics style)\n");
    160 		break;
    161 	case COLOR_OTHER:
    162 		__CTRACE(" (Other style)\n");
    163 		break;
    164 	}
    165 #endif
    166 
    167 	/*
    168 	 * Attributes that cannot be used with color.
    169 	 * Store these in an attr_t for wattrset()/wattron().
    170 	 */
    171 	_cursesi_screen->nca = __NORMAL;
    172 	if (__tc_NC != -1) {
    173 		temp_nc = (attr_t) t_getnum(_cursesi_screen->cursesi_genbuf, "NC");
    174 		if (temp_nc & 0x0001)
    175 			_cursesi_screen->nca |= __STANDOUT;
    176 		if (temp_nc & 0x0002)
    177 			_cursesi_screen->nca |= __UNDERSCORE;
    178 		if (temp_nc & 0x0004)
    179 			_cursesi_screen->nca |= __REVERSE;
    180 		if (temp_nc & 0x0008)
    181 			_cursesi_screen->nca |= __BLINK;
    182 		if (temp_nc & 0x0010)
    183 			_cursesi_screen->nca |= __DIM;
    184 		if (temp_nc & 0x0020)
    185 			_cursesi_screen->nca |= __BOLD;
    186 		if (temp_nc & 0x0040)
    187 			_cursesi_screen->nca |= __BLANK;
    188 		if (temp_nc & 0x0080)
    189 			_cursesi_screen->nca |= __PROTECT;
    190 		if (temp_nc & 0x0100)
    191 			_cursesi_screen->nca |= __ALTCHARSET;
    192 	}
    193 #ifdef DEBUG
    194 	__CTRACE ("start_color: _cursesi_screen->nca = %08x\n",
    195 	    _cursesi_screen->nca);
    196 #endif
    197 
    198 	/* Set up initial 8 colours */
    199 	if (COLORS >= COLOR_BLACK)
    200 		(void) init_color(COLOR_BLACK, 0, 0, 0);
    201 	if (COLORS >= COLOR_RED)
    202 		(void) init_color(COLOR_RED, 1000, 0, 0);
    203 	if (COLORS >= COLOR_GREEN)
    204 		(void) init_color(COLOR_GREEN, 0, 1000, 0);
    205 	if (COLORS >= COLOR_YELLOW)
    206 		(void) init_color(COLOR_YELLOW, 1000, 1000, 0);
    207 	if (COLORS >= COLOR_BLUE)
    208 		(void) init_color(COLOR_BLUE, 0, 0, 1000);
    209 	if (COLORS >= COLOR_MAGENTA)
    210 		(void) init_color(COLOR_MAGENTA, 1000, 0, 1000);
    211 	if (COLORS >= COLOR_CYAN)
    212 		(void) init_color(COLOR_CYAN, 0, 1000, 1000);
    213 	if (COLORS >= COLOR_WHITE)
    214 		(void) init_color(COLOR_WHITE, 1000, 1000, 1000);
    215 
    216 	/* Initialise other colours */
    217 	for (i = 8; i < COLORS; i++) {
    218 		_cursesi_screen->colours[i].red = 0;
    219 		_cursesi_screen->colours[i].green = 0;
    220 		_cursesi_screen->colours[i].blue = 0;
    221 		_cursesi_screen->colours[i].flags = 0;
    222 	}
    223 
    224 	/* Initialise pair 0 to default colours. */
    225 	_cursesi_screen->colour_pairs[0].fore = -1;
    226 	_cursesi_screen->colour_pairs[0].back = -1;
    227 	_cursesi_screen->colour_pairs[0].flags = 0;
    228 
    229 	/* Initialise user colour pairs to default (white on black) */
    230 	for (i = 0; i < COLOR_PAIRS; i++) {
    231 		_cursesi_screen->colour_pairs[i].fore = COLOR_WHITE;
    232 		_cursesi_screen->colour_pairs[i].back = COLOR_BLACK;
    233 		_cursesi_screen->colour_pairs[i].flags = 0;
    234 	}
    235 
    236 	/* Initialise default colour pair. */
    237 	_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore =
    238 	    __default_pair.fore;
    239 	_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back =
    240 	    __default_pair.back;
    241 	_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags =
    242 	    __default_pair.flags;
    243 
    244 	__using_color = 1;
    245 
    246 	/* Set all positions on all windows to curses default colours. */
    247 	for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) {
    248 		win = wlp->winp;
    249 		if (wlp->winp == curscr) {
    250 			/* Reset colour attribute on curscr */
    251 			for (y = 0; y < curscr->maxy; y++)
    252 				for (x = 0; x < curscr->maxx; x++) {
    253 					if ((curscr->lines[y]->line[x].battr & __COLOR) == __default_color)
    254 						curscr->lines[y]->line[x].battr &= ~__COLOR;
    255 				}
    256 		} else if (wlp->winp != __virtscr) {
    257 			/* Set background attribute on other windows */
    258 			if (!(win->battr & __COLOR))
    259 				win->battr |= __default_color;
    260 			for (y = 0; y < win->maxy; y++) {
    261 				for (x = 0; x < win->maxx; x++)
    262 					if (!(win->lines[y]->line[x].battr & __COLOR))
    263 						win->lines[y]->line[x].battr |= __default_color;
    264 			}
    265 			__touchwin(win);
    266 		}
    267 	}
    268 
    269 	return(OK);
    270 }
    271 
    272 /*
    273  * init_pair --
    274  *	Set pair foreground and background colors.
    275  *	Our default colour ordering is ANSI - 1 = red, 4 = blue, 3 = yellow,
    276  *	6 = cyan.  The older style (Sb/Sf) uses 1 = blue, 4 = red, 3 = cyan,
    277  *	6 = yellow, so we swap them here and in pair_content().
    278  */
    279 int
    280 init_pair(short pair, short fore, short back)
    281 {
    282 	int	changed;
    283 
    284 #ifdef DEBUG
    285 	__CTRACE("init_pair: %d, %d, %d\n", pair, fore, back);
    286 #endif
    287 
    288 	if (pair < 0 || pair >= COLOR_PAIRS)
    289 		return (ERR);
    290 	if (fore >= COLORS)
    291 		return (ERR);
    292 	if (back >= COLORS)
    293 		return (ERR);
    294 
    295 	/* Swap red/blue and yellow/cyan */
    296 	if (_cursesi_screen->color_type == COLOR_OTHER) {
    297 		switch (fore) {
    298 		case COLOR_RED:
    299 			fore = COLOR_BLUE;
    300 			break;
    301 		case COLOR_BLUE:
    302 			fore = COLOR_RED;
    303 			break;
    304 		case COLOR_YELLOW:
    305 			fore = COLOR_CYAN;
    306 			break;
    307 		case COLOR_CYAN:
    308 			fore = COLOR_YELLOW;
    309 			break;
    310 		}
    311 		switch (back) {
    312 		case COLOR_RED:
    313 			back = COLOR_BLUE;
    314 			break;
    315 		case COLOR_BLUE:
    316 			back = COLOR_RED;
    317 			break;
    318 		case COLOR_YELLOW:
    319 			back = COLOR_CYAN;
    320 			break;
    321 		case COLOR_CYAN:
    322 			back = COLOR_YELLOW;
    323 			break;
    324 		}
    325 	}
    326 
    327 	if ((_cursesi_screen->colour_pairs[pair].flags & __USED) &&
    328 	    (fore != _cursesi_screen->colour_pairs[pair].fore ||
    329 	     back != _cursesi_screen->colour_pairs[pair].back))
    330 		changed = 1;
    331 	else
    332 		changed = 0;
    333 
    334 	_cursesi_screen->colour_pairs[pair].flags |= __USED;
    335 	_cursesi_screen->colour_pairs[pair].fore = fore;
    336 	_cursesi_screen->colour_pairs[pair].back = back;
    337 
    338 	/* XXX: need to initialise HP style (Ip) */
    339 
    340 	if (changed)
    341 		__change_pair(pair);
    342 	return (OK);
    343 }
    344 
    345 /*
    346  * pair_content --
    347  *	Get pair foreground and background colours.
    348  */
    349 int
    350 pair_content(short pair, short *forep, short *backp)
    351 {
    352 	if (pair < 0 || pair > _cursesi_screen->COLOR_PAIRS)
    353 		return(ERR);
    354 
    355 	*forep = _cursesi_screen->colour_pairs[pair].fore;
    356 	*backp = _cursesi_screen->colour_pairs[pair].back;
    357 
    358 	/* Swap red/blue and yellow/cyan */
    359 	if (_cursesi_screen->color_type == COLOR_OTHER) {
    360 		switch (*forep) {
    361 		case COLOR_RED:
    362 			*forep = COLOR_BLUE;
    363 			break;
    364 		case COLOR_BLUE:
    365 			*forep = COLOR_RED;
    366 			break;
    367 		case COLOR_YELLOW:
    368 			*forep = COLOR_CYAN;
    369 			break;
    370 		case COLOR_CYAN:
    371 			*forep = COLOR_YELLOW;
    372 			break;
    373 		}
    374 		switch (*backp) {
    375 		case COLOR_RED:
    376 			*backp = COLOR_BLUE;
    377 			break;
    378 		case COLOR_BLUE:
    379 			*backp = COLOR_RED;
    380 			break;
    381 		case COLOR_YELLOW:
    382 			*backp = COLOR_CYAN;
    383 			break;
    384 		case COLOR_CYAN:
    385 			*backp = COLOR_YELLOW;
    386 			break;
    387 		}
    388 	}
    389 	return(OK);
    390 }
    391 
    392 /*
    393  * init_color --
    394  *	Set colour red, green and blue values.
    395  */
    396 int
    397 init_color(short color, short red, short green, short blue)
    398 {
    399 #ifdef DEBUG
    400 	__CTRACE("init_color: %d, %d, %d, %d\n", color, red, green, blue);
    401 #endif
    402 	if (color < 0 || color >= _cursesi_screen->COLORS)
    403 		return(ERR);
    404 
    405 	_cursesi_screen->colours[color].red = red;
    406 	_cursesi_screen->colours[color].green = green;
    407 	_cursesi_screen->colours[color].blue = blue;
    408 	/* XXX Not yet implemented */
    409 	return(ERR);
    410 	/* XXX: need to initialise Tek style (Ic) and support HLS */
    411 }
    412 
    413 /*
    414  * color_content --
    415  *	Get colour red, green and blue values.
    416  */
    417 int
    418 color_content(short color, short *redp, short *greenp, short *bluep)
    419 {
    420 	if (color < 0 || color >= _cursesi_screen->COLORS)
    421 		return(ERR);
    422 
    423 	*redp = _cursesi_screen->colours[color].red;
    424 	*greenp = _cursesi_screen->colours[color].green;
    425 	*bluep = _cursesi_screen->colours[color].blue;
    426 	return(OK);
    427 }
    428 
    429 /*
    430  * use_default_colors --
    431  *	Use terminal default colours instead of curses default colour.
    432   */
    433 int
    434 use_default_colors()
    435 {
    436 #ifdef DEBUG
    437 	__CTRACE("use_default_colors\n");
    438 #endif
    439 
    440 	return(assume_default_colors(-1, -1));
    441 }
    442 
    443 /*
    444  * assume_default_colors --
    445  *	Set the default foreground and background colours.
    446  */
    447 int
    448 assume_default_colors(short fore, short back)
    449 {
    450 #ifdef DEBUG
    451 	__CTRACE("assume_default_colors: %d, %d\n", fore, back);
    452 #endif
    453 	/* Swap red/blue and yellow/cyan */
    454 	if (_cursesi_screen->color_type == COLOR_OTHER) {
    455 		switch (fore) {
    456 		case COLOR_RED:
    457 			fore = COLOR_BLUE;
    458 			break;
    459 		case COLOR_BLUE:
    460 			fore = COLOR_RED;
    461 			break;
    462 		case COLOR_YELLOW:
    463 			fore = COLOR_CYAN;
    464 			break;
    465 		case COLOR_CYAN:
    466 			fore = COLOR_YELLOW;
    467 			break;
    468 		}
    469 		switch (back) {
    470 		case COLOR_RED:
    471 			back = COLOR_BLUE;
    472 			break;
    473 		case COLOR_BLUE:
    474 			back = COLOR_RED;
    475 			break;
    476 		case COLOR_YELLOW:
    477 			back = COLOR_CYAN;
    478 			break;
    479 		case COLOR_CYAN:
    480 			back = COLOR_YELLOW;
    481 			break;
    482 		}
    483 	}
    484 	__default_pair.fore = fore;
    485 	__default_pair.back = back;
    486 	__default_pair.flags = __USED;
    487 
    488 	if (COLOR_PAIRS) {
    489 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore = fore;
    490 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back = back;
    491 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags = __USED;
    492 	}
    493 
    494 	/*
    495 	 * If we've already called start_color(), make sure all instances
    496 	 * of the curses default colour pair are dirty.
    497 	 */
    498 	if (__using_color)
    499 		__change_pair(PAIR_NUMBER(__default_color));
    500 
    501 	return(OK);
    502 }
    503 
    504 /*
    505  * no_color_video --
    506  *	Return attributes that cannot be combined with color.
    507  */
    508 attr_t
    509 no_color_video(void)
    510 {
    511 	return(_cursesi_screen->nca);
    512 }
    513 
    514 /*
    515  * __set_color --
    516  *	Set terminal foreground and background colours.
    517  */
    518 void
    519 __set_color( /*ARGSUSED*/ WINDOW *win, attr_t attr)
    520 {
    521 	short	pair;
    522 
    523 	if ((curscr->wattr & __COLOR) == (attr & __COLOR))
    524 		return;
    525 
    526 	pair = PAIR_NUMBER((u_int32_t)attr);
    527 #ifdef DEBUG
    528 	__CTRACE("__set_color: %d, %d, %d\n", pair,
    529 		 _cursesi_screen->colour_pairs[pair].fore,
    530 		 _cursesi_screen->colour_pairs[pair].back);
    531 #endif
    532 	switch (_cursesi_screen->color_type) {
    533 	/* Set ANSI forground and background colours */
    534 	case COLOR_ANSI:
    535 		if (_cursesi_screen->colour_pairs[pair].fore < 0 ||
    536 		    _cursesi_screen->colour_pairs[pair].back < 0)
    537 			__unset_color(curscr);
    538 		if (_cursesi_screen->colour_pairs[pair].fore >= 0)
    539 			tputs(__parse_cap(_cursesi_screen->tc_AF,
    540 			    _cursesi_screen->colour_pairs[pair].fore),
    541 			    0, __cputchar);
    542 		if (_cursesi_screen->colour_pairs[pair].back >= 0)
    543 			tputs(__parse_cap(_cursesi_screen->tc_AB,
    544 			    _cursesi_screen->colour_pairs[pair].back),
    545 			    0, __cputchar);
    546 		break;
    547 	case COLOR_HP:
    548 		/* XXX: need to support HP style */
    549 		break;
    550 	case COLOR_TEK:
    551 		/* XXX: need to support Tek style */
    552 		break;
    553 	case COLOR_OTHER:
    554 		if (_cursesi_screen->colour_pairs[pair].fore < 0 ||
    555 		    _cursesi_screen->colour_pairs[pair].back < 0)
    556 			__unset_color(curscr);
    557 		if (_cursesi_screen->colour_pairs[pair].fore >= 0)
    558 			tputs(__parse_cap(_cursesi_screen->tc_Sf,
    559 			    _cursesi_screen->colour_pairs[pair].fore),
    560 			    0, __cputchar);
    561 		if (_cursesi_screen->colour_pairs[pair].back >= 0)
    562 			tputs(__parse_cap(_cursesi_screen->tc_Sb,
    563 			    _cursesi_screen->colour_pairs[pair].back),
    564 			    0, __cputchar);
    565 		break;
    566 	}
    567 	curscr->wattr &= ~__COLOR;
    568 	curscr->wattr |= attr & __COLOR;
    569 }
    570 
    571 /*
    572  * __unset_color --
    573  *	Clear terminal foreground and background colours.
    574  */
    575 void
    576 __unset_color(WINDOW *win)
    577 {
    578 #ifdef DEBUG
    579 	__CTRACE("__unset_color\n");
    580 #endif
    581 	switch (_cursesi_screen->color_type) {
    582 	/* Clear ANSI forground and background colours */
    583 	case COLOR_ANSI:
    584 		if (__tc_op != NULL) {
    585 			tputs(__tc_op, 0, __cputchar);
    586 			win->wattr &= __mask_op;
    587 		}
    588 		break;
    589 	case COLOR_HP:
    590 		/* XXX: need to support HP style */
    591 		break;
    592 	case COLOR_TEK:
    593 		/* XXX: need to support Tek style */
    594 		break;
    595 	case COLOR_OTHER:
    596 		if (__tc_op != NULL) {
    597 			tputs(__tc_op, 0, __cputchar);
    598 			win->wattr &= __mask_op;
    599 		}
    600 		break;
    601 	}
    602 }
    603 
    604 /*
    605  * __restore_colors --
    606  *	Redo color definitions after restarting 'curses' mode.
    607  */
    608 void
    609 __restore_colors(void)
    610 {
    611 	if (__tc_cc != 0)
    612 		switch (_cursesi_screen->color_type) {
    613 		case COLOR_HP:
    614 			/* XXX: need to re-initialise HP style (Ip) */
    615 			break;
    616 		case COLOR_TEK:
    617 			/* XXX: need to re-initialise Tek style (Ic) */
    618 			break;
    619 		}
    620 }
    621 
    622 /*
    623  * __change_pair --
    624  *	Mark dirty all positions using pair.
    625  */
    626 void
    627 __change_pair(short pair)
    628 {
    629 	struct __winlist	*wlp;
    630 	WINDOW			*win;
    631 	int			 y, x;
    632 	__LINE			*lp;
    633 	uint32_t		cl = COLOR_PAIR(pair);
    634 
    635 
    636 	for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) {
    637 #ifdef DEBUG
    638 		__CTRACE("__change_pair: win = %p\n", wlp->winp);
    639 #endif
    640 		win = wlp->winp;
    641 		if (win == __virtscr)
    642 			continue;
    643 
    644 		if (win == curscr) {
    645 			/* Reset colour attribute on curscr */
    646 #ifdef DEBUG
    647 			__CTRACE("__change_pair: win == curscr\n");
    648 #endif
    649 			for (y = 0; y < curscr->maxy; y++) {
    650 				lp = curscr->lines[y];
    651 				for (x = 0; x < curscr->maxx; x++) {
    652 					if ((lp->line[x].attr & __COLOR) == cl)
    653 						lp->line[x].attr &= ~__COLOR;
    654 					if ((lp->line[x].battr & __COLOR) == cl)
    655 						lp->line[x].battr &= ~__COLOR;
    656 				}
    657 			}
    658 			continue;
    659 		}
    660 
    661 		/* Mark dirty those positions with colour pair "pair" */
    662 		for (y = 0; y < win->maxy; y++) {
    663 			lp = curscr->lines[y];
    664 			for (x = 0; x < win->maxx; x++)
    665 				if ((lp->line[x].attr & __COLOR) == cl ||
    666 				    (lp->line[x].battr & __COLOR) == cl) {
    667 					if (!(lp->flags & __ISDIRTY))
    668 						lp->flags |= __ISDIRTY;
    669 					/*
    670 					 * firstchp/lastchp are shared
    671 					 * between parent window and
    672 					 * sub-window.
    673 					 */
    674 					if (*lp->firstchp > x)
    675 						*lp->firstchp = x;
    676 					if (*lp->lastchp < x)
    677 						*lp->lastchp = x;
    678 				}
    679 #ifdef DEBUG
    680 			if ((win->lines[y]->flags & __ISDIRTY))
    681 				__CTRACE("__change_pair: first = %d, last = %d\n", *win->lines[y]->firstchp, *win->lines[y]->lastchp);
    682 #endif
    683 		}
    684 	}
    685 }
    686