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