Home | History | Annotate | Line # | Download | only in libcurses
color.c revision 1.30
      1 /*	$NetBSD: color.c,v 1.30 2006/01/15 11:43:54 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.30 2006/01/15 11:43:54 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 != __virtscr && wlp->winp != curscr) {
    250 			/* Set color attribute on other windows */
    251 			win->battr |= __default_color;
    252 			for (y = 0; y < win->maxy; y++) {
    253 				for (x = 0; x < win->maxx; x++) {
    254 					win->lines[y]->line[x].attr &= ~__COLOR;
    255 					win->lines[y]->line[x].attr |= __default_color;
    256 				}
    257 			}
    258 			__touchwin(win);
    259 		}
    260 	}
    261 
    262 	return(OK);
    263 }
    264 
    265 /*
    266  * init_pair --
    267  *	Set pair foreground and background colors.
    268  *	Our default colour ordering is ANSI - 1 = red, 4 = blue, 3 = yellow,
    269  *	6 = cyan.  The older style (Sb/Sf) uses 1 = blue, 4 = red, 3 = cyan,
    270  *	6 = yellow, so we swap them here and in pair_content().
    271  */
    272 int
    273 init_pair(short pair, short fore, short back)
    274 {
    275 	int	changed;
    276 
    277 #ifdef DEBUG
    278 	__CTRACE("init_pair: %d, %d, %d\n", pair, fore, back);
    279 #endif
    280 
    281 	if (pair < 0 || pair >= COLOR_PAIRS)
    282 		return (ERR);
    283 	if (fore >= COLORS)
    284 		return (ERR);
    285 	if (back >= COLORS)
    286 		return (ERR);
    287 
    288 	/* Swap red/blue and yellow/cyan */
    289 	if (_cursesi_screen->color_type == COLOR_OTHER) {
    290 		switch (fore) {
    291 		case COLOR_RED:
    292 			fore = COLOR_BLUE;
    293 			break;
    294 		case COLOR_BLUE:
    295 			fore = COLOR_RED;
    296 			break;
    297 		case COLOR_YELLOW:
    298 			fore = COLOR_CYAN;
    299 			break;
    300 		case COLOR_CYAN:
    301 			fore = COLOR_YELLOW;
    302 			break;
    303 		}
    304 		switch (back) {
    305 		case COLOR_RED:
    306 			back = COLOR_BLUE;
    307 			break;
    308 		case COLOR_BLUE:
    309 			back = COLOR_RED;
    310 			break;
    311 		case COLOR_YELLOW:
    312 			back = COLOR_CYAN;
    313 			break;
    314 		case COLOR_CYAN:
    315 			back = COLOR_YELLOW;
    316 			break;
    317 		}
    318 	}
    319 
    320 	if ((_cursesi_screen->colour_pairs[pair].flags & __USED) &&
    321 	    (fore != _cursesi_screen->colour_pairs[pair].fore ||
    322 	     back != _cursesi_screen->colour_pairs[pair].back))
    323 		changed = 1;
    324 	else
    325 		changed = 0;
    326 
    327 	_cursesi_screen->colour_pairs[pair].flags |= __USED;
    328 	_cursesi_screen->colour_pairs[pair].fore = fore;
    329 	_cursesi_screen->colour_pairs[pair].back = back;
    330 
    331 	/* XXX: need to initialise HP style (Ip) */
    332 
    333 	if (changed)
    334 		__change_pair(pair);
    335 	return (OK);
    336 }
    337 
    338 /*
    339  * pair_content --
    340  *	Get pair foreground and background colours.
    341  */
    342 int
    343 pair_content(short pair, short *forep, short *backp)
    344 {
    345 	if (pair < 0 || pair > _cursesi_screen->COLOR_PAIRS)
    346 		return(ERR);
    347 
    348 	*forep = _cursesi_screen->colour_pairs[pair].fore;
    349 	*backp = _cursesi_screen->colour_pairs[pair].back;
    350 
    351 	/* Swap red/blue and yellow/cyan */
    352 	if (_cursesi_screen->color_type == COLOR_OTHER) {
    353 		switch (*forep) {
    354 		case COLOR_RED:
    355 			*forep = COLOR_BLUE;
    356 			break;
    357 		case COLOR_BLUE:
    358 			*forep = COLOR_RED;
    359 			break;
    360 		case COLOR_YELLOW:
    361 			*forep = COLOR_CYAN;
    362 			break;
    363 		case COLOR_CYAN:
    364 			*forep = COLOR_YELLOW;
    365 			break;
    366 		}
    367 		switch (*backp) {
    368 		case COLOR_RED:
    369 			*backp = COLOR_BLUE;
    370 			break;
    371 		case COLOR_BLUE:
    372 			*backp = COLOR_RED;
    373 			break;
    374 		case COLOR_YELLOW:
    375 			*backp = COLOR_CYAN;
    376 			break;
    377 		case COLOR_CYAN:
    378 			*backp = COLOR_YELLOW;
    379 			break;
    380 		}
    381 	}
    382 	return(OK);
    383 }
    384 
    385 /*
    386  * init_color --
    387  *	Set colour red, green and blue values.
    388  */
    389 int
    390 init_color(short color, short red, short green, short blue)
    391 {
    392 #ifdef DEBUG
    393 	__CTRACE("init_color: %d, %d, %d, %d\n", color, red, green, blue);
    394 #endif
    395 	if (color < 0 || color >= _cursesi_screen->COLORS)
    396 		return(ERR);
    397 
    398 	_cursesi_screen->colours[color].red = red;
    399 	_cursesi_screen->colours[color].green = green;
    400 	_cursesi_screen->colours[color].blue = blue;
    401 	/* XXX Not yet implemented */
    402 	return(ERR);
    403 	/* XXX: need to initialise Tek style (Ic) and support HLS */
    404 }
    405 
    406 /*
    407  * color_content --
    408  *	Get colour red, green and blue values.
    409  */
    410 int
    411 color_content(short color, short *redp, short *greenp, short *bluep)
    412 {
    413 	if (color < 0 || color >= _cursesi_screen->COLORS)
    414 		return(ERR);
    415 
    416 	*redp = _cursesi_screen->colours[color].red;
    417 	*greenp = _cursesi_screen->colours[color].green;
    418 	*bluep = _cursesi_screen->colours[color].blue;
    419 	return(OK);
    420 }
    421 
    422 /*
    423  * use_default_colors --
    424  *	Use terminal default colours instead of curses default colour.
    425   */
    426 int
    427 use_default_colors()
    428 {
    429 #ifdef DEBUG
    430 	__CTRACE("use_default_colors\n");
    431 #endif
    432 
    433 	return(assume_default_colors(-1, -1));
    434 }
    435 
    436 /*
    437  * assume_default_colors --
    438  *	Set the default foreground and background colours.
    439  */
    440 int
    441 assume_default_colors(short fore, short back)
    442 {
    443 #ifdef DEBUG
    444 	__CTRACE("assume_default_colors: %d, %d\n", fore, back);
    445 #endif
    446 	/* Swap red/blue and yellow/cyan */
    447 	if (_cursesi_screen->color_type == COLOR_OTHER) {
    448 		switch (fore) {
    449 		case COLOR_RED:
    450 			fore = COLOR_BLUE;
    451 			break;
    452 		case COLOR_BLUE:
    453 			fore = COLOR_RED;
    454 			break;
    455 		case COLOR_YELLOW:
    456 			fore = COLOR_CYAN;
    457 			break;
    458 		case COLOR_CYAN:
    459 			fore = COLOR_YELLOW;
    460 			break;
    461 		}
    462 		switch (back) {
    463 		case COLOR_RED:
    464 			back = COLOR_BLUE;
    465 			break;
    466 		case COLOR_BLUE:
    467 			back = COLOR_RED;
    468 			break;
    469 		case COLOR_YELLOW:
    470 			back = COLOR_CYAN;
    471 			break;
    472 		case COLOR_CYAN:
    473 			back = COLOR_YELLOW;
    474 			break;
    475 		}
    476 	}
    477 	__default_pair.fore = fore;
    478 	__default_pair.back = back;
    479 	__default_pair.flags = __USED;
    480 
    481 	if (COLOR_PAIRS) {
    482 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore = fore;
    483 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back = back;
    484 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags = __USED;
    485 	}
    486 
    487 	/*
    488 	 * If we've already called start_color(), make sure all instances
    489 	 * of the curses default colour pair are dirty.
    490 	 */
    491 	if (__using_color)
    492 		__change_pair(PAIR_NUMBER(__default_color));
    493 
    494 	return(OK);
    495 }
    496 
    497 /*
    498  * no_color_video --
    499  *	Return attributes that cannot be combined with color.
    500  */
    501 attr_t
    502 no_color_video(void)
    503 {
    504 	return(_cursesi_screen->nca);
    505 }
    506 
    507 /*
    508  * __set_color --
    509  *	Set terminal foreground and background colours.
    510  */
    511 void
    512 __set_color( /*ARGSUSED*/ WINDOW *win, attr_t attr)
    513 {
    514 	short	pair;
    515 
    516 	if ((curscr->wattr & __COLOR) == (attr & __COLOR))
    517 		return;
    518 
    519 	pair = PAIR_NUMBER((u_int32_t)attr);
    520 #ifdef DEBUG
    521 	__CTRACE("__set_color: %d, %d, %d\n", pair,
    522 		 _cursesi_screen->colour_pairs[pair].fore,
    523 		 _cursesi_screen->colour_pairs[pair].back);
    524 #endif
    525 	switch (_cursesi_screen->color_type) {
    526 	/* Set ANSI forground and background colours */
    527 	case COLOR_ANSI:
    528 		if (_cursesi_screen->colour_pairs[pair].fore < 0 ||
    529 		    _cursesi_screen->colour_pairs[pair].back < 0)
    530 			__unset_color(curscr);
    531 		if (_cursesi_screen->colour_pairs[pair].fore >= 0)
    532 			tputs(__parse_cap(_cursesi_screen->tc_AF,
    533 			    _cursesi_screen->colour_pairs[pair].fore),
    534 			    0, __cputchar);
    535 		if (_cursesi_screen->colour_pairs[pair].back >= 0)
    536 			tputs(__parse_cap(_cursesi_screen->tc_AB,
    537 			    _cursesi_screen->colour_pairs[pair].back),
    538 			    0, __cputchar);
    539 		break;
    540 	case COLOR_HP:
    541 		/* XXX: need to support HP style */
    542 		break;
    543 	case COLOR_TEK:
    544 		/* XXX: need to support Tek style */
    545 		break;
    546 	case COLOR_OTHER:
    547 		if (_cursesi_screen->colour_pairs[pair].fore < 0 ||
    548 		    _cursesi_screen->colour_pairs[pair].back < 0)
    549 			__unset_color(curscr);
    550 		if (_cursesi_screen->colour_pairs[pair].fore >= 0)
    551 			tputs(__parse_cap(_cursesi_screen->tc_Sf,
    552 			    _cursesi_screen->colour_pairs[pair].fore),
    553 			    0, __cputchar);
    554 		if (_cursesi_screen->colour_pairs[pair].back >= 0)
    555 			tputs(__parse_cap(_cursesi_screen->tc_Sb,
    556 			    _cursesi_screen->colour_pairs[pair].back),
    557 			    0, __cputchar);
    558 		break;
    559 	}
    560 	curscr->wattr &= ~__COLOR;
    561 	curscr->wattr |= attr & __COLOR;
    562 }
    563 
    564 /*
    565  * __unset_color --
    566  *	Clear terminal foreground and background colours.
    567  */
    568 void
    569 __unset_color(WINDOW *win)
    570 {
    571 #ifdef DEBUG
    572 	__CTRACE("__unset_color\n");
    573 #endif
    574 	switch (_cursesi_screen->color_type) {
    575 	/* Clear ANSI forground and background colours */
    576 	case COLOR_ANSI:
    577 		if (__tc_op != NULL) {
    578 			tputs(__tc_op, 0, __cputchar);
    579 			win->wattr &= __mask_op;
    580 		}
    581 		break;
    582 	case COLOR_HP:
    583 		/* XXX: need to support HP style */
    584 		break;
    585 	case COLOR_TEK:
    586 		/* XXX: need to support Tek style */
    587 		break;
    588 	case COLOR_OTHER:
    589 		if (__tc_op != NULL) {
    590 			tputs(__tc_op, 0, __cputchar);
    591 			win->wattr &= __mask_op;
    592 		}
    593 		break;
    594 	}
    595 }
    596 
    597 /*
    598  * __restore_colors --
    599  *	Redo color definitions after restarting 'curses' mode.
    600  */
    601 void
    602 __restore_colors(void)
    603 {
    604 	if (__tc_cc != 0)
    605 		switch (_cursesi_screen->color_type) {
    606 		case COLOR_HP:
    607 			/* XXX: need to re-initialise HP style (Ip) */
    608 			break;
    609 		case COLOR_TEK:
    610 			/* XXX: need to re-initialise Tek style (Ic) */
    611 			break;
    612 		}
    613 }
    614 
    615 /*
    616  * __change_pair --
    617  *	Mark dirty all positions using pair.
    618  */
    619 void
    620 __change_pair(short pair)
    621 {
    622 	struct __winlist	*wlp;
    623 	WINDOW			*win;
    624 	int			 y, x;
    625 	__LINE			*lp;
    626 	uint32_t		cl = COLOR_PAIR(pair);
    627 
    628 
    629 	for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) {
    630 #ifdef DEBUG
    631 		__CTRACE("__change_pair: win = %p\n", wlp->winp);
    632 #endif
    633 		win = wlp->winp;
    634 		if (win == __virtscr)
    635 			continue;
    636 		else if (win == curscr) {
    637 			/* Reset colour attribute on curscr */
    638 #ifdef DEBUG
    639 			__CTRACE("__change_pair: win == curscr\n");
    640 #endif
    641 			for (y = 0; y < curscr->maxy; y++) {
    642 				lp = curscr->lines[y];
    643 				for (x = 0; x < curscr->maxx; x++) {
    644 					if ((lp->line[x].attr & __COLOR) == cl)
    645 						lp->line[x].attr &= ~__COLOR;
    646 				}
    647 			}
    648 		} else {
    649 			/* Mark dirty those positions with colour pair "pair" */
    650 			for (y = 0; y < win->maxy; y++) {
    651 				lp = curscr->lines[y];
    652 				for (x = 0; x < win->maxx; x++)
    653 					if ((lp->line[x].attr &
    654 					    __COLOR) == cl) {
    655 						if (!(lp->flags & __ISDIRTY))
    656 							lp->flags |= __ISDIRTY;
    657 						/*
    658 					 	* firstchp/lastchp are shared
    659 					 	* between parent window and
    660 					 	* sub-window.
    661 					 	*/
    662 						if (*lp->firstchp > x)
    663 						*lp->firstchp = x;
    664 						if (*lp->lastchp < x)
    665 							*lp->lastchp = x;
    666 					}
    667 #ifdef DEBUG
    668 				if ((win->lines[y]->flags & __ISDIRTY))
    669 					__CTRACE("__change_pair: first = %d, last = %d\n", *win->lines[y]->firstchp, *win->lines[y]->lastchp);
    670 #endif
    671 			}
    672 		}
    673 	}
    674 }
    675