1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*LINTLIBRARY*/
43 
44 #include <sys/types.h>
45 #include "curses_inc.h"
46 
47 
48 static	void	_rgb_to_hls(float, float, float, int *, int *, int *);
49 static float	MAX(float, float, float), MIN(float, float, float);
50 
51 
52 int
53 init_color(short color, short r, short g, short b)
54 {
55 	_Color *ctp = cur_term->_color_tbl;  /* color table pointer */
56 
57 	/* check if terminal can change color and validity of the	    */
58 	/* first argument						    */
59 
60 	if (!can_change || color >= COLORS || color < 0)
61 		return (ERR);
62 
63 	/* if any of the last 3 arguments is out of 0 - 1000 range,	*/
64 	/* adjust them accordingly					*/
65 
66 	if (r > 1000)	r = 1000;
67 	if (g > 1000)	g = 1000;
68 	if (b > 1000)	b = 1000;
69 	if (r < 0)	r = 0;
70 	if (g < 0)	g = 0;
71 	if (b < 0)	b = 0;
72 
73 	/* if the call came from scr_reset, the color_table already	*/
74 	/* contains desired values, but we should still send escape seq. */
75 
76 	/* if new color is exactly the same as the old one, return */
77 
78 	if (ctp[color].r == r && ctp[color].g == g && ctp[color].b == b)
79 		return (OK);
80 
81 	/* update color table		*/
82 
83 	ctp[color].r = r;   ctp[color].g = g;    ctp[color].b = b;
84 
85 	/* all the occurrences of color on the screen must be changed   */
86 	/* to the new definition					*/
87 
88 	/* for terminals that can define individual colors (Tek model)  */
89 	/* send an escape sequence to define that color			*/
90 
91 	if (initialize_color) {
92 		if (hue_lightness_saturation) {
93 			int	h, s, l;
94 			_rgb_to_hls((float)r, (float)g, (float)b, &h, &l, &s);
95 			(void) tputs(tparm_p4(initialize_color, color, h, l, s),
96 			    1, _outch);
97 		} else
98 			(void) tputs(tparm_p4(initialize_color, color, r, g, b),
99 			    1, _outch);
100 
101 
102 	}
103 
104 	/* for terminals that can only define color pairs, go through   */
105 	/* pairs table, and re-initialize all pairs that use given color */
106 
107 	else {
108 		short i;
109 		_Color_pair *ptp = cur_term->_pairs_tbl;
110 		/* pairs table pointer */
111 		for (i = 0; i < COLOR_PAIRS; i++) {
112 			if (ptp[i].foreground == color ||
113 			    ptp[i].background == color)
114 				_init_HP_pair(i, ptp[i].foreground,
115 				    ptp[i].background);
116 		}
117 	}
118 	return (OK);
119 }
120 
121 
122 
123 
124 static void
125 _rgb_to_hls(float r, float g, float b, int *hh, int *ll, int *ss)
126 {
127 	float	rc, gc, bc, h, l, s;
128 	double	max, min;
129 
130 	r /= 1000;  g /= 1000;  b /= 1000;
131 
132 	max = MAX(r, g, b);
133 	min = MIN(r, g, b);
134 
135 	/* calculate lightness  */
136 
137 	l = (max + min) / 2;
138 
139 	/* calculate saturation */
140 
141 	if (max == min) {
142 		s = 0;
143 		h = 0;
144 	} else {
145 		if (l < 0.5)
146 			s = (max - min) / (max + min);
147 		else
148 			s = (max - min) / (2 - max - min);
149 
150 		/* calculate hue   */
151 
152 		rc = (max - r) / (max - min);
153 		gc = (max - g) / (max - min);
154 		bc = (max - b) / (max - min);
155 
156 		if (r == max)
157 			h = bc - gc;
158 		else if (g == max)
159 			h = 2 + rc - bc;
160 		else /* if (b == max) */
161 			h = 4 + gc - rc;
162 
163 		h = h * 60;
164 		if (h < 0.0)
165 			h = h + 360;
166 
167 		/* until here we have converted into HSL.  */
168 		/* Now, to convert into */
169 		/* Tektronix HLS, add 120 to h		*/
170 
171 		h = ((int)(h+120))%360;
172 	}
173 	*hh = (int) h;
174 	*ss = (int) (s * 100);
175 	*ll = (int) (l * 100);
176 }
177 
178 
179 static float
180 MAX(float a, float b, float c)
181 {
182 	if (a >= b)
183 		if (a >= c)
184 			return (a);
185 		else return (c);
186 	else if (c >= b)
187 		return (c);
188 	else return (b);
189 }
190 
191 static float
192 MIN(float a, float b, float c)
193 {
194 	if (a > b)
195 		if (b > c)
196 			return (c);
197 		else return (b);
198 	else if (a < c)
199 		return (a);
200 	else return (c);
201 }
202