xref: /minix3/lib/libcurses/color.c (revision 0c3ae37f525eceade8dc047e551f5c9cb33faeb1)
1*0c3ae37fSLionel Sambuc /*	$NetBSD: color.c,v 1.38 2011/10/03 12:32:15 roy Exp $	*/
251ffecc1SBen Gras 
351ffecc1SBen Gras /*
451ffecc1SBen Gras  * Copyright (c) 2000 The NetBSD Foundation, Inc.
551ffecc1SBen Gras  * All rights reserved.
651ffecc1SBen Gras  *
751ffecc1SBen Gras  * This code is derived from software contributed to The NetBSD Foundation
851ffecc1SBen Gras  * by Julian Coleman.
951ffecc1SBen Gras  *
1051ffecc1SBen Gras  * Redistribution and use in source and binary forms, with or without
1151ffecc1SBen Gras  * modification, are permitted provided that the following conditions
1251ffecc1SBen Gras  * are met:
1351ffecc1SBen Gras  * 1. Redistributions of source code must retain the above copyright
1451ffecc1SBen Gras  *    notice, this list of conditions and the following disclaimer.
1551ffecc1SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
1651ffecc1SBen Gras  *    notice, this list of conditions and the following disclaimer in the
1751ffecc1SBen Gras  *    documentation and/or other materials provided with the distribution.
1851ffecc1SBen Gras  *
1951ffecc1SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2051ffecc1SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2151ffecc1SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2251ffecc1SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2351ffecc1SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2451ffecc1SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2551ffecc1SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2651ffecc1SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2751ffecc1SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2851ffecc1SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2951ffecc1SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
3051ffecc1SBen Gras  */
3151ffecc1SBen Gras 
3251ffecc1SBen Gras #include <sys/cdefs.h>
3351ffecc1SBen Gras #ifndef lint
34*0c3ae37fSLionel Sambuc __RCSID("$NetBSD: color.c,v 1.38 2011/10/03 12:32:15 roy Exp $");
3551ffecc1SBen Gras #endif				/* not lint */
3651ffecc1SBen Gras 
3751ffecc1SBen Gras #include "curses.h"
3851ffecc1SBen Gras #include "curses_private.h"
3951ffecc1SBen Gras 
4051ffecc1SBen Gras /* Have we initialised colours? */
4151ffecc1SBen Gras int	__using_color = 0;
4251ffecc1SBen Gras 
4351ffecc1SBen Gras /* Default colour number */
4451ffecc1SBen Gras attr_t	__default_color = 0;
4551ffecc1SBen Gras 
4651ffecc1SBen Gras /* Default colour pair values - white on black. */
4751ffecc1SBen Gras struct __pair	__default_pair = {COLOR_WHITE, COLOR_BLACK, 0};
4851ffecc1SBen Gras 
4951ffecc1SBen Gras /* Default colour values */
5051ffecc1SBen Gras /* Flags for colours and pairs */
5151ffecc1SBen Gras #define	__USED		0x01
5251ffecc1SBen Gras 
5351ffecc1SBen Gras static void
5451ffecc1SBen Gras __change_pair(short);
5551ffecc1SBen Gras 
5651ffecc1SBen Gras /*
5751ffecc1SBen Gras  * has_colors --
5851ffecc1SBen Gras  *	Check if terminal has colours.
5951ffecc1SBen Gras  */
6051ffecc1SBen Gras bool
has_colors(void)6151ffecc1SBen Gras has_colors(void)
6251ffecc1SBen Gras {
6351ffecc1SBen Gras 	if (max_colors > 0 && max_pairs > 0 &&
6451ffecc1SBen Gras 	    ((set_a_foreground != NULL && set_a_background != NULL) ||
6551ffecc1SBen Gras 		initialize_pair != NULL || initialize_color != NULL ||
6651ffecc1SBen Gras 		(set_background != NULL && set_foreground != NULL)))
6751ffecc1SBen Gras 		return(TRUE);
6851ffecc1SBen Gras 	else
6951ffecc1SBen Gras 		return(FALSE);
7051ffecc1SBen Gras }
7151ffecc1SBen Gras 
7251ffecc1SBen Gras /*
7351ffecc1SBen Gras  * can_change_color --
7451ffecc1SBen Gras  *	Check if terminal can change colours.
7551ffecc1SBen Gras  */
7651ffecc1SBen Gras bool
can_change_color(void)7751ffecc1SBen Gras can_change_color(void)
7851ffecc1SBen Gras {
7951ffecc1SBen Gras 	if (can_change)
8051ffecc1SBen Gras 		return(TRUE);
8151ffecc1SBen Gras 	else
8251ffecc1SBen Gras 		return(FALSE);
8351ffecc1SBen Gras }
8451ffecc1SBen Gras 
8551ffecc1SBen Gras /*
8651ffecc1SBen Gras  * start_color --
8751ffecc1SBen Gras  *	Initialise colour support.
8851ffecc1SBen Gras  */
8951ffecc1SBen Gras int
start_color(void)9051ffecc1SBen Gras start_color(void)
9151ffecc1SBen Gras {
9251ffecc1SBen Gras 	int			 i;
9351ffecc1SBen Gras 	attr_t			 temp_nc;
9451ffecc1SBen Gras 	struct __winlist	*wlp;
9551ffecc1SBen Gras 	WINDOW			*win;
9651ffecc1SBen Gras 	int			 y, x;
9751ffecc1SBen Gras 
9851ffecc1SBen Gras 	if (has_colors() == FALSE)
9951ffecc1SBen Gras 		return(ERR);
10051ffecc1SBen Gras 
10151ffecc1SBen Gras 	/* Max colours and colour pairs */
10251ffecc1SBen Gras 	if (max_colors == -1)
10351ffecc1SBen Gras 		COLORS = 0;
10451ffecc1SBen Gras 	else {
10551ffecc1SBen Gras 		COLORS = max_colors > MAX_COLORS ? MAX_COLORS : max_colors;
10651ffecc1SBen Gras 		if (max_pairs == -1) {
10751ffecc1SBen Gras 			COLOR_PAIRS = 0;
10851ffecc1SBen Gras 			COLORS = 0;
10951ffecc1SBen Gras 		} else {
11051ffecc1SBen Gras 			COLOR_PAIRS = (max_pairs > MAX_PAIRS - 1 ?
11151ffecc1SBen Gras 			    MAX_PAIRS - 1 : max_pairs);
11251ffecc1SBen Gras 			 /* Use the last colour pair for curses default. */
11351ffecc1SBen Gras 			__default_color = COLOR_PAIR(MAX_PAIRS - 1);
11451ffecc1SBen Gras 		}
11551ffecc1SBen Gras 	}
11651ffecc1SBen Gras 	if (!COLORS)
11751ffecc1SBen Gras 		return (ERR);
11851ffecc1SBen Gras 
11951ffecc1SBen Gras 	_cursesi_screen->COLORS = COLORS;
12051ffecc1SBen Gras 	_cursesi_screen->COLOR_PAIRS = COLOR_PAIRS;
12151ffecc1SBen Gras 
12251ffecc1SBen Gras 	/* Reset terminal colour and colour pairs. */
12351ffecc1SBen Gras 	if (orig_colors != NULL)
12451ffecc1SBen Gras 		tputs(orig_colors, 0, __cputchar);
12551ffecc1SBen Gras 	if (orig_pair != NULL) {
12651ffecc1SBen Gras 		tputs(orig_pair, 0, __cputchar);
12751ffecc1SBen Gras 		curscr->wattr &= _cursesi_screen->mask_op;
12851ffecc1SBen Gras 	}
12951ffecc1SBen Gras 
13051ffecc1SBen Gras 	/* Type of colour manipulation - ANSI/TEK/HP/other */
13151ffecc1SBen Gras 	if (set_a_foreground != NULL && set_a_background != NULL)
13251ffecc1SBen Gras 		_cursesi_screen->color_type = COLOR_ANSI;
13351ffecc1SBen Gras 	else if (initialize_pair != NULL)
13451ffecc1SBen Gras 		_cursesi_screen->color_type = COLOR_HP;
13551ffecc1SBen Gras 	else if (initialize_color != NULL)
13651ffecc1SBen Gras 		_cursesi_screen->color_type = COLOR_TEK;
13751ffecc1SBen Gras 	else if (set_foreground != NULL && set_background != NULL)
13851ffecc1SBen Gras 		_cursesi_screen->color_type = COLOR_OTHER;
13951ffecc1SBen Gras 	else
14051ffecc1SBen Gras 		return(ERR);		/* Unsupported colour method */
14151ffecc1SBen Gras 
14251ffecc1SBen Gras #ifdef DEBUG
14351ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "start_color: COLORS = %d, COLOR_PAIRS = %d",
14451ffecc1SBen Gras 	    COLORS, COLOR_PAIRS);
14551ffecc1SBen Gras 	switch (_cursesi_screen->color_type) {
14651ffecc1SBen Gras 	case COLOR_ANSI:
14751ffecc1SBen Gras 		__CTRACE(__CTRACE_COLOR, " (ANSI style)\n");
14851ffecc1SBen Gras 		break;
14951ffecc1SBen Gras 	case COLOR_HP:
15051ffecc1SBen Gras 		__CTRACE(__CTRACE_COLOR, " (HP style)\n");
15151ffecc1SBen Gras 		break;
15251ffecc1SBen Gras 	case COLOR_TEK:
15351ffecc1SBen Gras 		__CTRACE(__CTRACE_COLOR, " (Tektronics style)\n");
15451ffecc1SBen Gras 		break;
15551ffecc1SBen Gras 	case COLOR_OTHER:
15651ffecc1SBen Gras 		__CTRACE(__CTRACE_COLOR, " (Other style)\n");
15751ffecc1SBen Gras 		break;
15851ffecc1SBen Gras 	}
15951ffecc1SBen Gras #endif
16051ffecc1SBen Gras 
16151ffecc1SBen Gras 	/*
16251ffecc1SBen Gras 	 * Attributes that cannot be used with color.
16351ffecc1SBen Gras 	 * Store these in an attr_t for wattrset()/wattron().
16451ffecc1SBen Gras 	 */
16551ffecc1SBen Gras 	_cursesi_screen->nca = __NORMAL;
16651ffecc1SBen Gras 	if (no_color_video != -1) {
16751ffecc1SBen Gras 		temp_nc = (attr_t) t_no_color_video(_cursesi_screen->term);
16851ffecc1SBen Gras 		if (temp_nc & 0x0001)
16951ffecc1SBen Gras 			_cursesi_screen->nca |= __STANDOUT;
17051ffecc1SBen Gras 		if (temp_nc & 0x0002)
17151ffecc1SBen Gras 			_cursesi_screen->nca |= __UNDERSCORE;
17251ffecc1SBen Gras 		if (temp_nc & 0x0004)
17351ffecc1SBen Gras 			_cursesi_screen->nca |= __REVERSE;
17451ffecc1SBen Gras 		if (temp_nc & 0x0008)
17551ffecc1SBen Gras 			_cursesi_screen->nca |= __BLINK;
17651ffecc1SBen Gras 		if (temp_nc & 0x0010)
17751ffecc1SBen Gras 			_cursesi_screen->nca |= __DIM;
17851ffecc1SBen Gras 		if (temp_nc & 0x0020)
17951ffecc1SBen Gras 			_cursesi_screen->nca |= __BOLD;
18051ffecc1SBen Gras 		if (temp_nc & 0x0040)
18151ffecc1SBen Gras 			_cursesi_screen->nca |= __BLANK;
18251ffecc1SBen Gras 		if (temp_nc & 0x0080)
18351ffecc1SBen Gras 			_cursesi_screen->nca |= __PROTECT;
18451ffecc1SBen Gras 		if (temp_nc & 0x0100)
18551ffecc1SBen Gras 			_cursesi_screen->nca |= __ALTCHARSET;
18651ffecc1SBen Gras 	}
18751ffecc1SBen Gras #ifdef DEBUG
18851ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "start_color: _cursesi_screen->nca = %08x\n",
18951ffecc1SBen Gras 	    _cursesi_screen->nca);
19051ffecc1SBen Gras #endif
19151ffecc1SBen Gras 
19251ffecc1SBen Gras 	/* Set up initial 8 colours */
19351ffecc1SBen Gras 	if (COLORS >= COLOR_BLACK)
19451ffecc1SBen Gras 		(void) init_color(COLOR_BLACK, 0, 0, 0);
19551ffecc1SBen Gras 	if (COLORS >= COLOR_RED)
19651ffecc1SBen Gras 		(void) init_color(COLOR_RED, 1000, 0, 0);
19751ffecc1SBen Gras 	if (COLORS >= COLOR_GREEN)
19851ffecc1SBen Gras 		(void) init_color(COLOR_GREEN, 0, 1000, 0);
19951ffecc1SBen Gras 	if (COLORS >= COLOR_YELLOW)
20051ffecc1SBen Gras 		(void) init_color(COLOR_YELLOW, 1000, 1000, 0);
20151ffecc1SBen Gras 	if (COLORS >= COLOR_BLUE)
20251ffecc1SBen Gras 		(void) init_color(COLOR_BLUE, 0, 0, 1000);
20351ffecc1SBen Gras 	if (COLORS >= COLOR_MAGENTA)
20451ffecc1SBen Gras 		(void) init_color(COLOR_MAGENTA, 1000, 0, 1000);
20551ffecc1SBen Gras 	if (COLORS >= COLOR_CYAN)
20651ffecc1SBen Gras 		(void) init_color(COLOR_CYAN, 0, 1000, 1000);
20751ffecc1SBen Gras 	if (COLORS >= COLOR_WHITE)
20851ffecc1SBen Gras 		(void) init_color(COLOR_WHITE, 1000, 1000, 1000);
20951ffecc1SBen Gras 
21051ffecc1SBen Gras 	/* Initialise other colours */
21151ffecc1SBen Gras 	for (i = 8; i < COLORS; i++) {
21251ffecc1SBen Gras 		_cursesi_screen->colours[i].red = 0;
21351ffecc1SBen Gras 		_cursesi_screen->colours[i].green = 0;
21451ffecc1SBen Gras 		_cursesi_screen->colours[i].blue = 0;
21551ffecc1SBen Gras 		_cursesi_screen->colours[i].flags = 0;
21651ffecc1SBen Gras 	}
21751ffecc1SBen Gras 
21851ffecc1SBen Gras 	/* Initialise pair 0 to default colours. */
21951ffecc1SBen Gras 	_cursesi_screen->colour_pairs[0].fore = -1;
22051ffecc1SBen Gras 	_cursesi_screen->colour_pairs[0].back = -1;
22151ffecc1SBen Gras 	_cursesi_screen->colour_pairs[0].flags = 0;
22251ffecc1SBen Gras 
22351ffecc1SBen Gras 	/* Initialise user colour pairs to default (white on black) */
22451ffecc1SBen Gras 	for (i = 0; i < COLOR_PAIRS; i++) {
22551ffecc1SBen Gras 		_cursesi_screen->colour_pairs[i].fore = COLOR_WHITE;
22651ffecc1SBen Gras 		_cursesi_screen->colour_pairs[i].back = COLOR_BLACK;
22751ffecc1SBen Gras 		_cursesi_screen->colour_pairs[i].flags = 0;
22851ffecc1SBen Gras 	}
22951ffecc1SBen Gras 
23051ffecc1SBen Gras 	/* Initialise default colour pair. */
23151ffecc1SBen Gras 	_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore =
23251ffecc1SBen Gras 	    __default_pair.fore;
23351ffecc1SBen Gras 	_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back =
23451ffecc1SBen Gras 	    __default_pair.back;
23551ffecc1SBen Gras 	_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags =
23651ffecc1SBen Gras 	    __default_pair.flags;
23751ffecc1SBen Gras 
23851ffecc1SBen Gras 	__using_color = 1;
23951ffecc1SBen Gras 
24051ffecc1SBen Gras 	/* Set all positions on all windows to curses default colours. */
24151ffecc1SBen Gras 	for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) {
24251ffecc1SBen Gras 		win = wlp->winp;
24351ffecc1SBen Gras 		if (wlp->winp != __virtscr && wlp->winp != curscr) {
24451ffecc1SBen Gras 			/* Set color attribute on other windows */
24551ffecc1SBen Gras 			win->battr |= __default_color;
24651ffecc1SBen Gras 			for (y = 0; y < win->maxy; y++) {
24751ffecc1SBen Gras 				for (x = 0; x < win->maxx; x++) {
24851ffecc1SBen Gras 					win->alines[y]->line[x].attr &= ~__COLOR;
24951ffecc1SBen Gras 					win->alines[y]->line[x].attr |= __default_color;
25051ffecc1SBen Gras 				}
25151ffecc1SBen Gras 			}
25251ffecc1SBen Gras 			__touchwin(win);
25351ffecc1SBen Gras 		}
25451ffecc1SBen Gras 	}
25551ffecc1SBen Gras 
25651ffecc1SBen Gras 	return(OK);
25751ffecc1SBen Gras }
25851ffecc1SBen Gras 
25951ffecc1SBen Gras /*
26051ffecc1SBen Gras  * init_pair --
26151ffecc1SBen Gras  *	Set pair foreground and background colors.
26251ffecc1SBen Gras  *	Our default colour ordering is ANSI - 1 = red, 4 = blue, 3 = yellow,
26351ffecc1SBen Gras  *	6 = cyan.  The older style (Sb/Sf) uses 1 = blue, 4 = red, 3 = cyan,
26451ffecc1SBen Gras  *	6 = yellow, so we swap them here and in pair_content().
26551ffecc1SBen Gras  */
26651ffecc1SBen Gras int
init_pair(short pair,short fore,short back)26751ffecc1SBen Gras init_pair(short pair, short fore, short back)
26851ffecc1SBen Gras {
26951ffecc1SBen Gras 	int	changed;
27051ffecc1SBen Gras 
27151ffecc1SBen Gras #ifdef DEBUG
27251ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "init_pair: %d, %d, %d\n", pair, fore, back);
27351ffecc1SBen Gras #endif
27451ffecc1SBen Gras 
27551ffecc1SBen Gras 	if (pair < 0 || pair >= COLOR_PAIRS)
27651ffecc1SBen Gras 		return (ERR);
27751ffecc1SBen Gras 
27851ffecc1SBen Gras 	if (pair == 0) /* Ignore request for pair 0, it is default. */
27951ffecc1SBen Gras 		return OK;
28051ffecc1SBen Gras 
28151ffecc1SBen Gras 	if (fore >= COLORS)
28251ffecc1SBen Gras 		return (ERR);
28351ffecc1SBen Gras 	if (back >= COLORS)
28451ffecc1SBen Gras 		return (ERR);
28551ffecc1SBen Gras 
28651ffecc1SBen Gras 	/* Swap red/blue and yellow/cyan */
28751ffecc1SBen Gras 	if (_cursesi_screen->color_type == COLOR_OTHER) {
28851ffecc1SBen Gras 		switch (fore) {
28951ffecc1SBen Gras 		case COLOR_RED:
29051ffecc1SBen Gras 			fore = COLOR_BLUE;
29151ffecc1SBen Gras 			break;
29251ffecc1SBen Gras 		case COLOR_BLUE:
29351ffecc1SBen Gras 			fore = COLOR_RED;
29451ffecc1SBen Gras 			break;
29551ffecc1SBen Gras 		case COLOR_YELLOW:
29651ffecc1SBen Gras 			fore = COLOR_CYAN;
29751ffecc1SBen Gras 			break;
29851ffecc1SBen Gras 		case COLOR_CYAN:
29951ffecc1SBen Gras 			fore = COLOR_YELLOW;
30051ffecc1SBen Gras 			break;
30151ffecc1SBen Gras 		}
30251ffecc1SBen Gras 		switch (back) {
30351ffecc1SBen Gras 		case COLOR_RED:
30451ffecc1SBen Gras 			back = COLOR_BLUE;
30551ffecc1SBen Gras 			break;
30651ffecc1SBen Gras 		case COLOR_BLUE:
30751ffecc1SBen Gras 			back = COLOR_RED;
30851ffecc1SBen Gras 			break;
30951ffecc1SBen Gras 		case COLOR_YELLOW:
31051ffecc1SBen Gras 			back = COLOR_CYAN;
31151ffecc1SBen Gras 			break;
31251ffecc1SBen Gras 		case COLOR_CYAN:
31351ffecc1SBen Gras 			back = COLOR_YELLOW;
31451ffecc1SBen Gras 			break;
31551ffecc1SBen Gras 		}
31651ffecc1SBen Gras 	}
31751ffecc1SBen Gras 
31851ffecc1SBen Gras 	if ((_cursesi_screen->colour_pairs[pair].flags & __USED) &&
31951ffecc1SBen Gras 	    (fore != _cursesi_screen->colour_pairs[pair].fore ||
32051ffecc1SBen Gras 	     back != _cursesi_screen->colour_pairs[pair].back))
32151ffecc1SBen Gras 		changed = 1;
32251ffecc1SBen Gras 	else
32351ffecc1SBen Gras 		changed = 0;
32451ffecc1SBen Gras 
32551ffecc1SBen Gras 	_cursesi_screen->colour_pairs[pair].flags |= __USED;
32651ffecc1SBen Gras 	_cursesi_screen->colour_pairs[pair].fore = fore;
32751ffecc1SBen Gras 	_cursesi_screen->colour_pairs[pair].back = back;
32851ffecc1SBen Gras 
32951ffecc1SBen Gras 	/* XXX: need to initialise HP style (Ip) */
33051ffecc1SBen Gras 
33151ffecc1SBen Gras 	if (changed)
33251ffecc1SBen Gras 		__change_pair(pair);
33351ffecc1SBen Gras 	return (OK);
33451ffecc1SBen Gras }
33551ffecc1SBen Gras 
33651ffecc1SBen Gras /*
33751ffecc1SBen Gras  * pair_content --
33851ffecc1SBen Gras  *	Get pair foreground and background colours.
33951ffecc1SBen Gras  */
34051ffecc1SBen Gras int
pair_content(short pair,short * forep,short * backp)34151ffecc1SBen Gras pair_content(short pair, short *forep, short *backp)
34251ffecc1SBen Gras {
34351ffecc1SBen Gras 	if (pair < 0 || pair > _cursesi_screen->COLOR_PAIRS)
34451ffecc1SBen Gras 		return(ERR);
34551ffecc1SBen Gras 
34651ffecc1SBen Gras 	*forep = _cursesi_screen->colour_pairs[pair].fore;
34751ffecc1SBen Gras 	*backp = _cursesi_screen->colour_pairs[pair].back;
34851ffecc1SBen Gras 
34951ffecc1SBen Gras 	/* Swap red/blue and yellow/cyan */
35051ffecc1SBen Gras 	if (_cursesi_screen->color_type == COLOR_OTHER) {
35151ffecc1SBen Gras 		switch (*forep) {
35251ffecc1SBen Gras 		case COLOR_RED:
35351ffecc1SBen Gras 			*forep = COLOR_BLUE;
35451ffecc1SBen Gras 			break;
35551ffecc1SBen Gras 		case COLOR_BLUE:
35651ffecc1SBen Gras 			*forep = COLOR_RED;
35751ffecc1SBen Gras 			break;
35851ffecc1SBen Gras 		case COLOR_YELLOW:
35951ffecc1SBen Gras 			*forep = COLOR_CYAN;
36051ffecc1SBen Gras 			break;
36151ffecc1SBen Gras 		case COLOR_CYAN:
36251ffecc1SBen Gras 			*forep = COLOR_YELLOW;
36351ffecc1SBen Gras 			break;
36451ffecc1SBen Gras 		}
36551ffecc1SBen Gras 		switch (*backp) {
36651ffecc1SBen Gras 		case COLOR_RED:
36751ffecc1SBen Gras 			*backp = COLOR_BLUE;
36851ffecc1SBen Gras 			break;
36951ffecc1SBen Gras 		case COLOR_BLUE:
37051ffecc1SBen Gras 			*backp = COLOR_RED;
37151ffecc1SBen Gras 			break;
37251ffecc1SBen Gras 		case COLOR_YELLOW:
37351ffecc1SBen Gras 			*backp = COLOR_CYAN;
37451ffecc1SBen Gras 			break;
37551ffecc1SBen Gras 		case COLOR_CYAN:
37651ffecc1SBen Gras 			*backp = COLOR_YELLOW;
37751ffecc1SBen Gras 			break;
37851ffecc1SBen Gras 		}
37951ffecc1SBen Gras 	}
38051ffecc1SBen Gras 	return(OK);
38151ffecc1SBen Gras }
38251ffecc1SBen Gras 
38351ffecc1SBen Gras /*
38451ffecc1SBen Gras  * init_color --
38551ffecc1SBen Gras  *	Set colour red, green and blue values.
38651ffecc1SBen Gras  */
38751ffecc1SBen Gras int
init_color(short color,short red,short green,short blue)38851ffecc1SBen Gras init_color(short color, short red, short green, short blue)
38951ffecc1SBen Gras {
39051ffecc1SBen Gras #ifdef DEBUG
39151ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "init_color: %d, %d, %d, %d\n",
39251ffecc1SBen Gras 	    color, red, green, blue);
39351ffecc1SBen Gras #endif
39451ffecc1SBen Gras 	if (color < 0 || color >= _cursesi_screen->COLORS)
39551ffecc1SBen Gras 		return(ERR);
39651ffecc1SBen Gras 
39751ffecc1SBen Gras 	_cursesi_screen->colours[color].red = red;
39851ffecc1SBen Gras 	_cursesi_screen->colours[color].green = green;
39951ffecc1SBen Gras 	_cursesi_screen->colours[color].blue = blue;
40051ffecc1SBen Gras 	/* XXX Not yet implemented */
40151ffecc1SBen Gras 	return(ERR);
40251ffecc1SBen Gras 	/* XXX: need to initialise Tek style (Ic) and support HLS */
40351ffecc1SBen Gras }
40451ffecc1SBen Gras 
40551ffecc1SBen Gras /*
40651ffecc1SBen Gras  * color_content --
40751ffecc1SBen Gras  *	Get colour red, green and blue values.
40851ffecc1SBen Gras  */
40951ffecc1SBen Gras int
color_content(short color,short * redp,short * greenp,short * bluep)41051ffecc1SBen Gras color_content(short color, short *redp, short *greenp, short *bluep)
41151ffecc1SBen Gras {
41251ffecc1SBen Gras 	if (color < 0 || color >= _cursesi_screen->COLORS)
41351ffecc1SBen Gras 		return(ERR);
41451ffecc1SBen Gras 
41551ffecc1SBen Gras 	*redp = _cursesi_screen->colours[color].red;
41651ffecc1SBen Gras 	*greenp = _cursesi_screen->colours[color].green;
41751ffecc1SBen Gras 	*bluep = _cursesi_screen->colours[color].blue;
41851ffecc1SBen Gras 	return(OK);
41951ffecc1SBen Gras }
42051ffecc1SBen Gras 
42151ffecc1SBen Gras /*
42251ffecc1SBen Gras  * use_default_colors --
42351ffecc1SBen Gras  *	Use terminal default colours instead of curses default colour.
42451ffecc1SBen Gras   */
42551ffecc1SBen Gras int
use_default_colors()42651ffecc1SBen Gras use_default_colors()
42751ffecc1SBen Gras {
42851ffecc1SBen Gras #ifdef DEBUG
42951ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "use_default_colors\n");
43051ffecc1SBen Gras #endif
43151ffecc1SBen Gras 
43251ffecc1SBen Gras 	return(assume_default_colors(-1, -1));
43351ffecc1SBen Gras }
43451ffecc1SBen Gras 
43551ffecc1SBen Gras /*
43651ffecc1SBen Gras  * assume_default_colors --
43751ffecc1SBen Gras  *	Set the default foreground and background colours.
43851ffecc1SBen Gras  */
43951ffecc1SBen Gras int
assume_default_colors(short fore,short back)44051ffecc1SBen Gras assume_default_colors(short fore, short back)
44151ffecc1SBen Gras {
44251ffecc1SBen Gras #ifdef DEBUG
44351ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "assume_default_colors: %d, %d\n",
44451ffecc1SBen Gras 	    fore, back);
44551ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "assume_default_colors: default_colour = %d, pair_number = %d\n", __default_color, PAIR_NUMBER(__default_color));
44651ffecc1SBen Gras #endif
44751ffecc1SBen Gras 
44851ffecc1SBen Gras 	/* Swap red/blue and yellow/cyan */
44951ffecc1SBen Gras 	if (_cursesi_screen->color_type == COLOR_OTHER) {
45051ffecc1SBen Gras 		switch (fore) {
45151ffecc1SBen Gras 		case COLOR_RED:
45251ffecc1SBen Gras 			fore = COLOR_BLUE;
45351ffecc1SBen Gras 			break;
45451ffecc1SBen Gras 		case COLOR_BLUE:
45551ffecc1SBen Gras 			fore = COLOR_RED;
45651ffecc1SBen Gras 			break;
45751ffecc1SBen Gras 		case COLOR_YELLOW:
45851ffecc1SBen Gras 			fore = COLOR_CYAN;
45951ffecc1SBen Gras 			break;
46051ffecc1SBen Gras 		case COLOR_CYAN:
46151ffecc1SBen Gras 			fore = COLOR_YELLOW;
46251ffecc1SBen Gras 			break;
46351ffecc1SBen Gras 		}
46451ffecc1SBen Gras 		switch (back) {
46551ffecc1SBen Gras 		case COLOR_RED:
46651ffecc1SBen Gras 			back = COLOR_BLUE;
46751ffecc1SBen Gras 			break;
46851ffecc1SBen Gras 		case COLOR_BLUE:
46951ffecc1SBen Gras 			back = COLOR_RED;
47051ffecc1SBen Gras 			break;
47151ffecc1SBen Gras 		case COLOR_YELLOW:
47251ffecc1SBen Gras 			back = COLOR_CYAN;
47351ffecc1SBen Gras 			break;
47451ffecc1SBen Gras 		case COLOR_CYAN:
47551ffecc1SBen Gras 			back = COLOR_YELLOW;
47651ffecc1SBen Gras 			break;
47751ffecc1SBen Gras 		}
47851ffecc1SBen Gras 	}
47951ffecc1SBen Gras 	__default_pair.fore = fore;
48051ffecc1SBen Gras 	__default_pair.back = back;
48151ffecc1SBen Gras 	__default_pair.flags = __USED;
48251ffecc1SBen Gras 
48351ffecc1SBen Gras 	if (COLOR_PAIRS) {
48451ffecc1SBen Gras 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore = fore;
48551ffecc1SBen Gras 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back = back;
48651ffecc1SBen Gras 		_cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags = __USED;
48751ffecc1SBen Gras 	}
48851ffecc1SBen Gras 
48951ffecc1SBen Gras 	/*
49051ffecc1SBen Gras 	 * If we've already called start_color(), make sure all instances
49151ffecc1SBen Gras 	 * of the curses default colour pair are dirty.
49251ffecc1SBen Gras 	 */
49351ffecc1SBen Gras 	if (__using_color)
49451ffecc1SBen Gras 		__change_pair(PAIR_NUMBER(__default_color));
49551ffecc1SBen Gras 
49651ffecc1SBen Gras 	return(OK);
49751ffecc1SBen Gras }
49851ffecc1SBen Gras 
49951ffecc1SBen Gras /* no_color_video is a terminfo macro, but we need to retain binary compat */
50051ffecc1SBen Gras #ifdef __strong_alias
50151ffecc1SBen Gras #undef no_color_video
__strong_alias(no_color_video,no_color_attributes)50251ffecc1SBen Gras __strong_alias(no_color_video, no_color_attributes)
50351ffecc1SBen Gras #endif
50451ffecc1SBen Gras /*
50551ffecc1SBen Gras  * no_color_attributes --
50651ffecc1SBen Gras  *	Return attributes that cannot be combined with color.
50751ffecc1SBen Gras  */
50851ffecc1SBen Gras attr_t
50951ffecc1SBen Gras no_color_attributes(void)
51051ffecc1SBen Gras {
51151ffecc1SBen Gras 	return(_cursesi_screen->nca);
51251ffecc1SBen Gras }
51351ffecc1SBen Gras 
51451ffecc1SBen Gras /*
51551ffecc1SBen Gras  * __set_color --
51651ffecc1SBen Gras  *	Set terminal foreground and background colours.
51751ffecc1SBen Gras  */
51851ffecc1SBen Gras void
__set_color(WINDOW * win,attr_t attr)51951ffecc1SBen Gras __set_color( /*ARGSUSED*/ WINDOW *win, attr_t attr)
52051ffecc1SBen Gras {
52151ffecc1SBen Gras 	short	pair;
52251ffecc1SBen Gras 
52351ffecc1SBen Gras 	if ((curscr->wattr & __COLOR) == (attr & __COLOR))
52451ffecc1SBen Gras 		return;
52551ffecc1SBen Gras 
52651ffecc1SBen Gras 	pair = PAIR_NUMBER((u_int32_t)attr);
52751ffecc1SBen Gras #ifdef DEBUG
52851ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "__set_color: %d, %d, %d\n", pair,
52951ffecc1SBen Gras 		 _cursesi_screen->colour_pairs[pair].fore,
53051ffecc1SBen Gras 		 _cursesi_screen->colour_pairs[pair].back);
53151ffecc1SBen Gras #endif
53251ffecc1SBen Gras 	switch (_cursesi_screen->color_type) {
53351ffecc1SBen Gras 	/* Set ANSI forground and background colours */
53451ffecc1SBen Gras 	case COLOR_ANSI:
53551ffecc1SBen Gras 		if (_cursesi_screen->colour_pairs[pair].fore < 0 ||
53651ffecc1SBen Gras 		    _cursesi_screen->colour_pairs[pair].back < 0)
53751ffecc1SBen Gras 			__unset_color(curscr);
53851ffecc1SBen Gras 		if (_cursesi_screen->colour_pairs[pair].fore >= 0)
539*0c3ae37fSLionel Sambuc 			tputs(tiparm(t_set_a_foreground(_cursesi_screen->term),
540*0c3ae37fSLionel Sambuc 			    (int)_cursesi_screen->colour_pairs[pair].fore),
54151ffecc1SBen Gras 			    0, __cputchar);
54251ffecc1SBen Gras 		if (_cursesi_screen->colour_pairs[pair].back >= 0)
543*0c3ae37fSLionel Sambuc 			tputs(tiparm(t_set_a_background(_cursesi_screen->term),
544*0c3ae37fSLionel Sambuc 			    (int)_cursesi_screen->colour_pairs[pair].back),
54551ffecc1SBen Gras 			    0, __cputchar);
54651ffecc1SBen Gras 		break;
54751ffecc1SBen Gras 	case COLOR_HP:
54851ffecc1SBen Gras 		/* XXX: need to support HP style */
54951ffecc1SBen Gras 		break;
55051ffecc1SBen Gras 	case COLOR_TEK:
55151ffecc1SBen Gras 		/* XXX: need to support Tek style */
55251ffecc1SBen Gras 		break;
55351ffecc1SBen Gras 	case COLOR_OTHER:
55451ffecc1SBen Gras 		if (_cursesi_screen->colour_pairs[pair].fore < 0 ||
55551ffecc1SBen Gras 		    _cursesi_screen->colour_pairs[pair].back < 0)
55651ffecc1SBen Gras 			__unset_color(curscr);
55751ffecc1SBen Gras 		if (_cursesi_screen->colour_pairs[pair].fore >= 0)
558*0c3ae37fSLionel Sambuc 			tputs(tiparm(t_set_foreground(_cursesi_screen->term),
559*0c3ae37fSLionel Sambuc 			    (int)_cursesi_screen->colour_pairs[pair].fore),
56051ffecc1SBen Gras 			    0, __cputchar);
56151ffecc1SBen Gras 		if (_cursesi_screen->colour_pairs[pair].back >= 0)
562*0c3ae37fSLionel Sambuc 			tputs(tiparm(t_set_background(_cursesi_screen->term),
563*0c3ae37fSLionel Sambuc 			    (int)_cursesi_screen->colour_pairs[pair].back),
56451ffecc1SBen Gras 			    0, __cputchar);
56551ffecc1SBen Gras 		break;
56651ffecc1SBen Gras 	}
56751ffecc1SBen Gras 	curscr->wattr &= ~__COLOR;
56851ffecc1SBen Gras 	curscr->wattr |= attr & __COLOR;
56951ffecc1SBen Gras }
57051ffecc1SBen Gras 
57151ffecc1SBen Gras /*
57251ffecc1SBen Gras  * __unset_color --
57351ffecc1SBen Gras  *	Clear terminal foreground and background colours.
57451ffecc1SBen Gras  */
57551ffecc1SBen Gras void
__unset_color(WINDOW * win)57651ffecc1SBen Gras __unset_color(WINDOW *win)
57751ffecc1SBen Gras {
57851ffecc1SBen Gras #ifdef DEBUG
57951ffecc1SBen Gras 	__CTRACE(__CTRACE_COLOR, "__unset_color\n");
58051ffecc1SBen Gras #endif
58151ffecc1SBen Gras 	switch (_cursesi_screen->color_type) {
58251ffecc1SBen Gras 	/* Clear ANSI forground and background colours */
58351ffecc1SBen Gras 	case COLOR_ANSI:
58451ffecc1SBen Gras 		if (orig_pair != NULL) {
58551ffecc1SBen Gras 			tputs(orig_pair, 0, __cputchar);
58651ffecc1SBen Gras 			win->wattr &= __mask_op;
58751ffecc1SBen Gras 		}
58851ffecc1SBen Gras 		break;
58951ffecc1SBen Gras 	case COLOR_HP:
59051ffecc1SBen Gras 		/* XXX: need to support HP style */
59151ffecc1SBen Gras 		break;
59251ffecc1SBen Gras 	case COLOR_TEK:
59351ffecc1SBen Gras 		/* XXX: need to support Tek style */
59451ffecc1SBen Gras 		break;
59551ffecc1SBen Gras 	case COLOR_OTHER:
59651ffecc1SBen Gras 		if (orig_pair != NULL) {
59751ffecc1SBen Gras 			tputs(orig_pair, 0, __cputchar);
59851ffecc1SBen Gras 			win->wattr &= __mask_op;
59951ffecc1SBen Gras 		}
60051ffecc1SBen Gras 		break;
60151ffecc1SBen Gras 	}
60251ffecc1SBen Gras }
60351ffecc1SBen Gras 
60451ffecc1SBen Gras /*
60551ffecc1SBen Gras  * __restore_colors --
60651ffecc1SBen Gras  *	Redo color definitions after restarting 'curses' mode.
60751ffecc1SBen Gras  */
60851ffecc1SBen Gras void
__restore_colors(void)60951ffecc1SBen Gras __restore_colors(void)
61051ffecc1SBen Gras {
61151ffecc1SBen Gras 	if (can_change != 0)
61251ffecc1SBen Gras 		switch (_cursesi_screen->color_type) {
61351ffecc1SBen Gras 		case COLOR_HP:
61451ffecc1SBen Gras 			/* XXX: need to re-initialise HP style (Ip) */
61551ffecc1SBen Gras 			break;
61651ffecc1SBen Gras 		case COLOR_TEK:
61751ffecc1SBen Gras 			/* XXX: need to re-initialise Tek style (Ic) */
61851ffecc1SBen Gras 			break;
61951ffecc1SBen Gras 		}
62051ffecc1SBen Gras }
62151ffecc1SBen Gras 
62251ffecc1SBen Gras /*
62351ffecc1SBen Gras  * __change_pair --
62451ffecc1SBen Gras  *	Mark dirty all positions using pair.
62551ffecc1SBen Gras  */
62651ffecc1SBen Gras void
__change_pair(short pair)62751ffecc1SBen Gras __change_pair(short pair)
62851ffecc1SBen Gras {
62951ffecc1SBen Gras 	struct __winlist	*wlp;
63051ffecc1SBen Gras 	WINDOW			*win;
63151ffecc1SBen Gras 	int			 y, x;
63251ffecc1SBen Gras 	__LINE			*lp;
63351ffecc1SBen Gras 	uint32_t		cl = COLOR_PAIR(pair);
63451ffecc1SBen Gras 
63551ffecc1SBen Gras 
63651ffecc1SBen Gras 	for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) {
63751ffecc1SBen Gras #ifdef DEBUG
63851ffecc1SBen Gras 		__CTRACE(__CTRACE_COLOR, "__change_pair: win = %p\n",
63951ffecc1SBen Gras 		    wlp->winp);
64051ffecc1SBen Gras #endif
64151ffecc1SBen Gras 		win = wlp->winp;
64251ffecc1SBen Gras 		if (win == __virtscr)
64351ffecc1SBen Gras 			continue;
64451ffecc1SBen Gras 		else if (win == curscr) {
64551ffecc1SBen Gras 			/* Reset colour attribute on curscr */
64651ffecc1SBen Gras #ifdef DEBUG
64751ffecc1SBen Gras 			__CTRACE(__CTRACE_COLOR,
64851ffecc1SBen Gras 			    "__change_pair: win == curscr\n");
64951ffecc1SBen Gras #endif
65051ffecc1SBen Gras 			for (y = 0; y < curscr->maxy; y++) {
65151ffecc1SBen Gras 				lp = curscr->alines[y];
65251ffecc1SBen Gras 				for (x = 0; x < curscr->maxx; x++) {
65351ffecc1SBen Gras 					if ((lp->line[x].attr & __COLOR) == cl)
65451ffecc1SBen Gras 						lp->line[x].attr &= ~__COLOR;
65551ffecc1SBen Gras 				}
65651ffecc1SBen Gras 			}
65751ffecc1SBen Gras 		} else {
65851ffecc1SBen Gras 			/* Mark dirty those positions with colour pair "pair" */
65951ffecc1SBen Gras 			for (y = 0; y < win->maxy; y++) {
66051ffecc1SBen Gras 				lp = win->alines[y];
66151ffecc1SBen Gras 				for (x = 0; x < win->maxx; x++)
66251ffecc1SBen Gras 					if ((lp->line[x].attr &
66351ffecc1SBen Gras 					    __COLOR) == cl) {
66451ffecc1SBen Gras 						if (!(lp->flags & __ISDIRTY))
66551ffecc1SBen Gras 							lp->flags |= __ISDIRTY;
66651ffecc1SBen Gras 						/*
66751ffecc1SBen Gras 					 	* firstchp/lastchp are shared
66851ffecc1SBen Gras 					 	* between parent window and
66951ffecc1SBen Gras 					 	* sub-window.
67051ffecc1SBen Gras 					 	*/
67151ffecc1SBen Gras 						if (*lp->firstchp > x)
67251ffecc1SBen Gras 						*lp->firstchp = x;
67351ffecc1SBen Gras 						if (*lp->lastchp < x)
67451ffecc1SBen Gras 							*lp->lastchp = x;
67551ffecc1SBen Gras 					}
67651ffecc1SBen Gras #ifdef DEBUG
67751ffecc1SBen Gras 				if ((win->alines[y]->flags & __ISDIRTY))
67851ffecc1SBen Gras 					__CTRACE(__CTRACE_COLOR,
67951ffecc1SBen Gras 					    "__change_pair: first = %d, "
68051ffecc1SBen Gras 					    "last = %d\n",
68151ffecc1SBen Gras 					    *win->alines[y]->firstchp,
68251ffecc1SBen Gras 					    *win->alines[y]->lastchp);
68351ffecc1SBen Gras #endif
68451ffecc1SBen Gras 			}
68551ffecc1SBen Gras 		}
68651ffecc1SBen Gras 	}
68751ffecc1SBen Gras }
688