1 /* $TOG: Color.c /main/13 1998/09/23 19:36:49 samborn $ */
2 /*
3  * Motif
4  *
5  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6  *
7  * These libraries and programs are free software; you can
8  * redistribute them and/or modify them under the terms of the GNU
9  * Lesser General Public License as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * These libraries and programs are distributed in the hope that
14  * they will be useful, but WITHOUT ANY WARRANTY; without even the
15  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE. See the GNU Lesser General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with these librararies and programs; if not, write
21  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22  * Floor, Boston, MA 02110-1301 USA
23  */
24 /*
25  * HISTORY
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <X11/IntrinsicP.h>
36 #include <X11/ShellP.h>
37 #include <Xm/ManagerP.h>
38 #include <Xm/PrimitiveP.h>
39 #include <Xm/XmP.h>
40 #include <Xm/XmosP.h>		/* for bzero */
41 #include "ColorI.h"
42 #include "ImageCachI.h"
43 #include "MessagesI.h"
44 #include "ScreenI.h"
45 #include "XmI.h"
46 #ifdef FIX_1381
47 #include <Xm/XpmP.h>
48 #endif
49 
50 #define FIX_1500
51 
52 /* Warning and Error messages */
53 
54 #define MESSAGE0	_XmMMsgVisual_0000
55 #define MESSAGE1	_XmMMsgVisual_0001
56 #define MESSAGE2	_XmMMsgVisual_0002
57 
58 
59 /********    Static Function Declarations    ********/
60 
61 static void GetDefaultThresholdsForScreen(
62                         Screen *screen) ;
63 static XmColorData * GetDefaultColors(
64                         Screen *screen,
65                         Colormap color_map) ;
66 static Pixel GetBlackPixel(
67                         Screen *screen,
68                         Colormap colormap,
69                         XColor blackcolor) ;
70 static Pixel GetWhitePixel(
71                         Screen *screen,
72                         Colormap colormap,
73                         XColor whitecolor) ;
74 static void SetMonochromeColors(
75                         XmColorData *colors) ;
76 static int Brightness(
77                         XColor *color) ;
78 static void CalculateColorsForLightBackground(
79                         XColor *bg_color,
80                         XColor *fg_color,
81                         XColor *sel_color,
82                         XColor *ts_color,
83                         XColor *bs_color) ;
84 static void CalculateColorsForDarkBackground(
85                         XColor *bg_color,
86                         XColor *fg_color,
87                         XColor *sel_color,
88                         XColor *ts_color,
89                         XColor *bs_color) ;
90 static void CalculateColorsForMediumBackground(
91                         XColor *bg_color,
92                         XColor *fg_color,
93                         XColor *sel_color,
94                         XColor *ts_color,
95                         XColor *bs_color) ;
96 static void CalculateColorsRGB(
97                         XColor *bg_color,
98                         XColor *fg_color,
99                         XColor *sel_color,
100                         XColor *ts_color,
101                         XColor *bs_color) ;
102 static Pixel AccessColorData(
103                         XmColorData *cd,
104                         unsigned char which) ;
105 static XmColorData * GetColors(
106                         Screen *screen,
107                         Colormap color_map,
108                         Pixel background) ;
109 #ifdef FIX_1381
110 static unsigned int FromColorToBlackAndWhite(
111                         char *col) ;
112 #endif
113 
114 
115 /********    End Static Function Declarations    ********/
116 
117 
118 
119 /*
120  * GLOBAL VARIABLES
121  *
122  * These variables define the color cache.
123  */
124 static int Set_Count=0, Set_Size=0;
125 static XmColorData *Color_Set=NULL;
126 
127 
128 /* Thresholds for brightness
129    above LITE threshold, LITE color model is used
130    below DARK threshold, DARK color model is be used
131    use STD color model in between */
132 
133 static int XmCOLOR_LITE_THRESHOLD;
134 static int XmCOLOR_DARK_THRESHOLD;
135 static int XmFOREGROUND_THRESHOLD;
136 static Boolean XmTHRESHOLDS_INITD = FALSE;
137 
138 
139 /* DEPRECATED : use XmScreen resource now */
140 static XmColorProc ColorRGBCalcProc = CalculateColorsRGB;
141 
142 
143 static void
GetDefaultThresholdsForScreen(Screen * screen)144 GetDefaultThresholdsForScreen( Screen *screen )
145 {
146   XmScreen xmScreen;
147   int	   default_light_threshold_spec;
148   int	   default_dark_threshold_spec;
149   int	   default_foreground_threshold_spec;
150 
151   _XmProcessLock();
152   XmTHRESHOLDS_INITD = True;
153   _XmProcessUnlock();
154 
155   xmScreen = (XmScreen) XmGetXmScreen(screen);
156 
157   /* Get resources from the XmScreen */
158   default_light_threshold_spec = xmScreen->screen.lightThreshold;
159   default_dark_threshold_spec = xmScreen->screen.darkThreshold;
160   default_foreground_threshold_spec = xmScreen->screen.foregroundThreshold;
161 
162   if ((default_light_threshold_spec <= 0) ||
163       (default_light_threshold_spec > 100))
164     default_light_threshold_spec = XmDEFAULT_LIGHT_THRESHOLD;
165 
166   if ((default_dark_threshold_spec <= 0) ||
167       (default_dark_threshold_spec > 100))
168     default_dark_threshold_spec = XmDEFAULT_DARK_THRESHOLD;
169 
170   if ((default_foreground_threshold_spec <= 0) ||
171       (default_foreground_threshold_spec > 100))
172     default_foreground_threshold_spec = XmDEFAULT_FOREGROUND_THRESHOLD;
173 
174   _XmProcessLock();
175   XmCOLOR_LITE_THRESHOLD = default_light_threshold_spec * XmCOLOR_PERCENTILE;
176   XmCOLOR_DARK_THRESHOLD = default_dark_threshold_spec * XmCOLOR_PERCENTILE;
177   XmFOREGROUND_THRESHOLD = default_foreground_threshold_spec * XmCOLOR_PERCENTILE;
178   _XmProcessUnlock();
179 }
180 
GetDefaultBackgroundColor(Screen * screen,Colormap color_map)181 static XColor *GetDefaultBackgroundColor(Screen *screen, Colormap color_map)
182 {
183   XrmName names[2];
184   XrmClass classes[2];
185   XrmRepresentation rep;
186   XrmValue db_value;
187   static XColor color;
188 
189   names[0] = XrmPermStringToQuark(XmNbackground);
190   names[1] = NULLQUARK;
191 
192   classes[0] = XrmPermStringToQuark(XmCBackground);
193   classes[1] = NULLQUARK;
194 
195   if (XrmQGetResource(XtScreenDatabase(screen), names, classes,
196 		      &rep, &db_value))
197      {
198        if (rep == XrmPermStringToQuark(XmRString)) {
199 	 if (!XParseColor(DisplayOfScreen(screen), color_map, db_value.addr,
200 			  &color)) return NULL;
201        }
202        else if (rep == XrmPermStringToQuark(XmRPixel)) {
203 	 color.pixel = *(Pixel *) db_value.addr;
204 
205 	 XQueryColor(DisplayOfScreen(screen), color_map, &color);
206        }
207      }
208   else {
209     if (!XParseColor(DisplayOfScreen(screen), color_map, XmDEFAULT_BACKGROUND,
210 		     &color)) return NULL;
211   }
212 
213   return &color;
214 }
215 
216 static XmColorData *
GetDefaultColors(Screen * screen,Colormap color_map)217 GetDefaultColors(
218         Screen *screen,
219         Colormap color_map )
220 {
221 	static XmColorData * default_set = NULL;
222 	static int default_set_count = 0;
223 	static int default_set_size = 0;
224 	register int i;
225 	XColor *color_def;
226 	static Pixel background;
227         XrmValue fromVal;
228         XrmValue toVal;
229         XrmValue args[2];
230         Cardinal num_args;
231 	String default_string = XtDefaultBackground;
232 	XmColorData *result;
233 
234 	_XmProcessLock();
235 
236 	/*  Look through  a set of screen / background pairs to see  */
237 	/*  if the default is already in the table.                  */
238 
239 	for (i = 0; i < default_set_count; i++)
240 	{
241 	if ((default_set[i].screen == screen) &&
242 		(default_set[i].color_map == color_map))
243 	    {
244 	        result = default_set + i;
245 		_XmProcessUnlock();
246 		return result;
247 	    }
248 	}
249 
250 	/*  See if more space is needed in the array  */
251 
252 	if (default_set == NULL)
253 	{
254 		default_set_size = 10;
255 		default_set = (XmColorData *) XtRealloc((char *) default_set,
256 			(sizeof(XmColorData) * default_set_size));
257 
258 	}
259 	else if (default_set_count == default_set_size)
260 	{
261 		default_set_size += 10;
262 		default_set = (XmColorData *) XtRealloc((char *) default_set,
263 			sizeof(XmColorData) * default_set_size);
264 	}
265 
266 	/* Find the background based on the depth of the screen */
267 	if (DefaultDepthOfScreen(screen) == 1)
268         {
269 	  /*
270 	   * Fix for 4603 - Convert the string XtDefaultBackground into a Pixel
271 	   *                value using the XToolkit converter.  This converter
272 	   *                will set this value to WhitePixelOfScreen if reverse
273 	   *                video is not on, and to BlackPixelOfScreen if reverse
274 	   *                video is on.
275 	   */
276 	  args[0].addr = (XPointer) &screen;
277 	  args[0].size = sizeof(Screen*);
278 	  args[1].addr = (XPointer) &color_map;
279 	  args[1].size = sizeof(Colormap);
280 	  num_args = 2;
281 
282 	  fromVal.addr = default_string;
283 	  fromVal.size = strlen(default_string);
284 
285 	  toVal.addr = (XPointer) &background;
286 	  toVal.size = sizeof(Pixel);
287 
288 	  if(!XtCallConverter(DisplayOfScreen(screen),XtCvtStringToPixel,
289 			      args, num_args, &fromVal, &toVal, NULL))
290 	    background = WhitePixelOfScreen(screen);
291         }
292 
293 	else
294 	{
295 		/*  Parse out a color for the default background  */
296 
297 		if ((color_def = GetDefaultBackgroundColor(screen,
298 							   color_map)) !=
299 		    NULL)
300 		{
301 		    XmAllocColorProc aproc =
302 			_XmGetColorAllocationProc(screen);
303 		    if (aproc == NULL)
304 			aproc = DEFAULT_ALLOCCOLOR_PROC;
305 
306 			if ((*aproc)(DisplayOfScreen(screen), color_map,
307 				color_def))
308 			{
309 				background = color_def->pixel;
310 			}
311 			else
312 			{
313 				XtWarning(MESSAGE1);
314 				background = WhitePixelOfScreen(screen);
315 			}
316 		}
317 		else
318 		{
319 			XtWarning(MESSAGE2);
320 			background = WhitePixelOfScreen(screen);
321 		}
322 	}
323 
324 	/*
325 	 * Get the color data generated and save it in the next open
326 	 * slot in the default set array.  default_set points to a subset
327 	 * of the data pointed to by color_set (defined in GetColors).
328 	 */
329 
330 	default_set[default_set_count] =
331 		*GetColors(screen, color_map, background);
332 	default_set_count++;
333 
334 	result = default_set + (default_set_count - 1);
335 	_XmProcessUnlock();
336 	return result;
337 }
338 
339 
340 
341 Boolean
_XmSearchColorCache(unsigned int which,XmColorData * values,XmColorData ** ret)342 _XmSearchColorCache(
343         unsigned int which,
344         XmColorData *values,
345         XmColorData **ret )
346 {
347     register int i;
348 
349     /*
350      * Look through  a set of screen, color_map, background triplets
351      * to see if these colors have already been generated.
352      */
353 
354     _XmProcessLock();
355     for (i = 0; i < Set_Count; i++) {
356 	if ( (!(which & XmLOOK_AT_SCREEN) ||
357 	      ((Color_Set + i)->screen == values->screen))
358 	    &&
359 	    (!(which & XmLOOK_AT_CMAP) ||
360 	     ((Color_Set + i)->color_map == values->color_map))
361 	    &&
362 	    (!(which & XmLOOK_AT_BACKGROUND) ||
363 	     (((Color_Set + i)->allocated & XmBACKGROUND) &&
364 	      ((Color_Set + i)->background.pixel ==
365 	       values->background.pixel)))
366 	    &&
367 	    (!(which & XmLOOK_AT_FOREGROUND) ||
368 	     (((Color_Set + i)->allocated & XmFOREGROUND) &&
369 	      ((Color_Set + i)->foreground.pixel ==
370 	       values->foreground.pixel)))
371 	    &&
372 	    (!(which & XmLOOK_AT_TOP_SHADOW) ||
373 	     (((Color_Set + i)->allocated & XmTOP_SHADOW) &&
374 	      ((Color_Set + i)->top_shadow.pixel ==
375 	       values->top_shadow.pixel)))
376 	    &&
377 	    (!(which & XmLOOK_AT_BOTTOM_SHADOW) ||
378 	     (((Color_Set + i)->allocated & XmBOTTOM_SHADOW) &&
379 	      ((Color_Set+ i)->bottom_shadow.pixel ==
380 	       values->bottom_shadow.pixel)))
381 	    &&
382 	    (!(which & XmLOOK_AT_SELECT) ||
383 	     (((Color_Set + i)->allocated & XmSELECT) &&
384 	      ((Color_Set + i)->select.pixel ==
385 	       values->select.pixel))))
386 	    {
387 		*ret = (Color_Set + i);
388 		_XmProcessUnlock();
389 		return (TRUE);
390 	    }
391     }
392 
393     *ret = NULL;
394     _XmProcessUnlock();
395     return (FALSE);
396 }
397 
398 XmColorData *
_XmAddToColorCache(XmColorData * new_rec)399 _XmAddToColorCache(
400         XmColorData *new_rec )
401 {
402        XmColorData *result;
403 
404 	/*  See if more space is needed */
405 	_XmProcessLock();
406 	if (Set_Count == Set_Size)
407 	{
408 		Set_Size += 10;
409 		Color_Set = (XmColorData *)XtRealloc((char *) Color_Set,
410 			sizeof(XmColorData) * Set_Size);
411 	}
412 
413 	*(Color_Set + Set_Count) = *new_rec;
414 	Set_Count++;
415 
416 	result = Color_Set + (Set_Count - 1);
417 	_XmProcessUnlock();
418 
419 	return result;
420 }
421 
422 
423 static Pixel
GetBlackPixel(Screen * screen,Colormap colormap,XColor blackcolor)424 GetBlackPixel(
425 	      Screen *screen,
426 	      Colormap colormap,
427 	      XColor blackcolor )
428 {
429   Pixel p;
430   XmAllocColorProc aproc = _XmGetColorAllocationProc(screen);
431 
432   if (aproc == NULL)
433       aproc = DEFAULT_ALLOCCOLOR_PROC;
434 
435   blackcolor.red = 0;
436   blackcolor.green = 0;
437   blackcolor.blue = 0;
438 
439   if (colormap == DefaultColormapOfScreen(screen))
440     p = blackcolor.pixel = BlackPixelOfScreen(screen);
441   else if ((*aproc)(screen->display, colormap, &blackcolor))
442     p = blackcolor.pixel;
443   else
444     p = blackcolor.pixel = BlackPixelOfScreen(screen); /* fallback pixel */
445 
446   return (p);
447 }
448 
449 
450 static Pixel
GetWhitePixel(Screen * screen,Colormap colormap,XColor whitecolor)451 GetWhitePixel(
452 	      Screen *screen,
453 	      Colormap colormap,
454 	      XColor whitecolor )
455 {
456   Pixel p;
457   XmAllocColorProc aproc = _XmGetColorAllocationProc(screen);
458 
459   if (aproc == NULL)
460       aproc = DEFAULT_ALLOCCOLOR_PROC;
461 
462   whitecolor.red = XmMAX_SHORT;
463   whitecolor.green = XmMAX_SHORT;
464   whitecolor.blue = XmMAX_SHORT;
465 
466   if (colormap == DefaultColormapOfScreen(screen))
467     p = whitecolor.pixel = WhitePixelOfScreen(screen);
468   else if ((*aproc)(screen->display, colormap, &whitecolor))
469     p = whitecolor.pixel;
470   else
471     p = whitecolor.pixel = WhitePixelOfScreen(screen); /* fallback pixel */
472   return (p);
473 }
474 
475 static Pixel
AccessColorData(XmColorData * cd,unsigned char which)476 AccessColorData(
477         XmColorData *cd,
478         unsigned char which )
479 {
480     Pixel p;
481     XmAllocColorProc aproc = _XmGetColorAllocationProc(cd->screen);
482 
483     if (aproc == NULL)
484 	aproc = DEFAULT_ALLOCCOLOR_PROC;
485 
486     switch(which) {
487     case XmBACKGROUND:
488 	if (!(cd->allocated & which) &&
489 	    ((*aproc)(cd->screen->display,
490 		      cd->color_map, &(cd->background)) == 0)) {
491 	    if (Brightness(&(cd->background))
492 		< XmFOREGROUND_THRESHOLD )
493 		cd->background.pixel = GetBlackPixel(cd->screen,
494 						     cd->color_map,
495 						     cd->background);
496 	    else
497 		cd->background.pixel = GetWhitePixel(cd->screen,
498 						     cd->color_map,
499 						     cd->background);
500 	    XQueryColor(cd->screen->display, cd->color_map,
501 			&(cd->background));
502 	}
503 	p = cd->background.pixel;
504 	cd->allocated |= which;
505 	break;
506     case XmFOREGROUND:
507 	if (!(cd->allocated & which) &&
508 	    ((*aproc)(cd->screen->display,
509 		      cd->color_map, &(cd->foreground)) == 0 ))
510 	    {
511 		if (Brightness(&(cd->background))
512 		    < XmFOREGROUND_THRESHOLD )
513 		    cd->foreground.pixel = GetWhitePixel(cd->screen,
514 							 cd->color_map,
515 							 cd->foreground);
516 		else
517 		    cd->foreground.pixel = GetBlackPixel(cd->screen,
518 							 cd->color_map,
519 							 cd->foreground);
520 		XQueryColor(cd->screen->display, cd->color_map,
521 			    &(cd->foreground));
522 	    }
523 	p =  cd->foreground.pixel;
524 	cd->allocated |= which;
525 	break;
526     case XmTOP_SHADOW:
527 	if (!(cd->allocated & which) &&
528 	    ((*aproc)(cd->screen->display,
529 		      cd->color_map, &(cd->top_shadow)) == 0))
530 	    {
531 		if (Brightness(&(cd->background))
532 		    > XmCOLOR_LITE_THRESHOLD)
533 		    cd->top_shadow.pixel =
534 			GetBlackPixel(cd->screen, cd->color_map,
535 				      cd->top_shadow);
536 		else
537 		    cd->top_shadow.pixel =
538 			GetWhitePixel(cd->screen, cd->color_map,
539 				      cd->top_shadow);
540 		XQueryColor(cd->screen->display, cd->color_map,
541 			    &(cd->top_shadow));
542 
543 	    }
544 	p = cd->top_shadow.pixel;
545 	cd->allocated |= which;
546 	break;
547     case XmBOTTOM_SHADOW:
548 	if (!(cd->allocated & which) &&
549 	    ((*aproc)(cd->screen->display,
550 		      cd->color_map, &(cd->bottom_shadow)) == 0))
551 	    {
552 		if (Brightness(&(cd->background))
553 		    < XmCOLOR_DARK_THRESHOLD)
554 		    cd->bottom_shadow.pixel =
555 			GetWhitePixel(cd->screen, cd->color_map,
556 				      cd->bottom_shadow);
557 		else
558 		    cd->bottom_shadow.pixel =
559 			GetBlackPixel(cd->screen, cd->color_map,
560 				      cd->bottom_shadow);
561 		XQueryColor(cd->screen->display, cd->color_map,
562 			    &(cd->bottom_shadow));
563 	    }
564 	p = cd->bottom_shadow.pixel;
565 	cd->allocated |= which;
566 	break;
567     case XmSELECT:
568 	if (!(cd->allocated & which) &&
569 	    ((*aproc)(cd->screen->display,
570 		      cd->color_map, &(cd->select)) == 0))
571 	    {
572 		if (Brightness(&(cd->background))
573 		    < XmFOREGROUND_THRESHOLD)
574 		    cd->select.pixel = GetWhitePixel(cd->screen,
575 						     cd->color_map,
576 						     cd->select);
577 		else
578 		    cd->select.pixel = GetBlackPixel(cd->screen,
579 						     cd->color_map,
580 						     cd->select);
581 		XQueryColor(cd->screen->display, cd->color_map,
582 			    &(cd->select));
583 	    }
584 	p = cd->select.pixel;
585 	cd->allocated |= which;
586 	break;
587     default:
588 	XtWarning(MESSAGE0);
589 	p = GetBlackPixel(cd->screen, cd->color_map, cd->background);
590 	break;
591     }
592 
593     return(p);
594 }
595 
596 static void
SetMonochromeColors(XmColorData * colors)597 SetMonochromeColors(
598         XmColorData *colors )
599 {
600 	Screen *screen = colors->screen;
601 	Pixel background = colors->background.pixel;
602 
603 	if (background == BlackPixelOfScreen(screen))
604 	{
605 		colors->foreground.pixel = WhitePixelOfScreen (screen);
606 		colors->foreground.red = colors->foreground.green =
607 			colors->foreground.blue = XmMAX_SHORT;
608 
609 		colors->bottom_shadow.pixel = WhitePixelOfScreen(screen);
610 		colors->bottom_shadow.red = colors->bottom_shadow.green =
611 			colors->bottom_shadow.blue = XmMAX_SHORT;
612 
613 		colors->select.pixel = WhitePixelOfScreen(screen);
614 		colors->select.red = colors->select.green =
615 			colors->select.blue = XmMAX_SHORT;
616 
617 		colors->top_shadow.pixel = BlackPixelOfScreen(screen);
618 		colors->top_shadow.red = colors->top_shadow.green =
619 			colors->top_shadow.blue = 0;
620 	}
621 	else if (background == WhitePixelOfScreen(screen))
622 	{
623 		colors->foreground.pixel = BlackPixelOfScreen(screen);
624 		colors->foreground.red = colors->foreground.green =
625 			colors->foreground.blue = 0;
626 
627 		colors->top_shadow.pixel = WhitePixelOfScreen(screen);
628 		colors->top_shadow.red = colors->top_shadow.green =
629 			colors->top_shadow.blue = XmMAX_SHORT;
630 
631 		colors->bottom_shadow.pixel = BlackPixelOfScreen(screen);
632 		colors->bottom_shadow.red = colors->bottom_shadow.green =
633 			colors->bottom_shadow.blue = 0;
634 
635 		colors->select.pixel = BlackPixelOfScreen(screen);
636 		colors->select.red = colors->select.green =
637 			colors->select.blue = 0;
638 	}
639 
640 	colors->allocated |= (XmFOREGROUND | XmTOP_SHADOW
641 		| XmBOTTOM_SHADOW | XmSELECT);
642 }
643 
644 static int
Brightness(XColor * color)645 Brightness(
646         XColor *color )
647 {
648 	int brightness;
649 	int intensity;
650 	int light;
651 	int luminosity, maxprimary, minprimary;
652 	int red = color->red;
653 	int green = color->green;
654 	int blue = color->blue;
655 
656 	intensity = (red + green + blue) / 3;
657 
658 	/*
659 	 * The casting nonsense below is to try to control the point at
660 	 * the truncation occurs.
661 	 */
662 
663 	luminosity = (int) ((XmRED_LUMINOSITY * (float) red)
664 		+ (XmGREEN_LUMINOSITY * (float) green)
665 		+ (XmBLUE_LUMINOSITY * (float) blue));
666 
667 	maxprimary = ( (red > green) ?
668 					( (red > blue) ? red : blue ) :
669 					( (green > blue) ? green : blue ) );
670 
671 	minprimary = ( (red < green) ?
672 					( (red < blue) ? red : blue ) :
673 					( (green < blue) ? green : blue ) );
674 
675 	light = (minprimary + maxprimary) / 2;
676 
677 	brightness = ( (intensity * XmINTENSITY_FACTOR) +
678 				   (light * XmLIGHT_FACTOR) +
679 				   (luminosity * XmLUMINOSITY_FACTOR) ) / 100;
680 	return(brightness);
681 }
682 
683 static void
CalculateColorsForLightBackground(XColor * bg_color,XColor * fg_color,XColor * sel_color,XColor * ts_color,XColor * bs_color)684 CalculateColorsForLightBackground(
685         XColor *bg_color,
686         XColor *fg_color,
687         XColor *sel_color,
688         XColor *ts_color,
689         XColor *bs_color )
690 {
691 	int brightness = Brightness(bg_color);
692 	int color_value;
693 
694 	if (fg_color)
695 	{
696 /*
697  * Fix for 4602 - Compare the brightness with the foreground threshold.
698  *                If its larger, make the foreground color black.
699  *                Otherwise, make it white.
700  */
701           if (brightness > XmFOREGROUND_THRESHOLD)
702           {
703                   fg_color->red = 0;
704                   fg_color->green = 0;
705                   fg_color->blue = 0;
706           }
707           else
708           {
709                   fg_color->red = XmMAX_SHORT;
710                   fg_color->green = XmMAX_SHORT;
711                   fg_color->blue = XmMAX_SHORT;
712           }
713 /*
714  * End Fix 4602
715  */
716 	}
717 
718 	if (sel_color)
719 	{
720 		color_value = bg_color->red;
721 		color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
722 		sel_color->red = color_value;
723 
724 		color_value = bg_color->green;
725 		color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
726 		sel_color->green = color_value;
727 
728 		color_value = bg_color->blue;
729 		color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
730 		sel_color->blue = color_value;
731 	}
732 
733 	if (bs_color)
734 	{
735 		color_value = bg_color->red;
736 		color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
737 		bs_color->red = color_value;
738 
739 		color_value = bg_color->green;
740 		color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
741 		bs_color->green = color_value;
742 
743 		color_value = bg_color->blue;
744 		color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
745 		bs_color->blue = color_value;
746 	}
747 
748 	if (ts_color)
749 	{
750 		color_value = bg_color->red;
751 		color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
752 		ts_color->red = color_value;
753 
754 		color_value = bg_color->green;
755 		color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
756 		ts_color->green = color_value;
757 
758 		color_value = bg_color->blue;
759 		color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
760 		ts_color->blue = color_value;
761 	}
762 }
763 
764 static void
CalculateColorsForDarkBackground(XColor * bg_color,XColor * fg_color,XColor * sel_color,XColor * ts_color,XColor * bs_color)765 CalculateColorsForDarkBackground(
766         XColor *bg_color,
767         XColor *fg_color,
768         XColor *sel_color,
769         XColor *ts_color,
770         XColor *bs_color )
771 {
772 	int brightness = Brightness(bg_color);
773 	int color_value;
774 
775 	if (fg_color)
776 	{
777 /*
778  * Fix for 4602 - Compare the brightness with the foreground threshold.
779  *                If its larger, make the foreground color black.
780  *                Otherwise, make it white.
781  */
782           if (brightness > XmFOREGROUND_THRESHOLD)
783           {
784                   fg_color->red = 0;
785                   fg_color->green = 0;
786                   fg_color->blue = 0;
787           }
788           else
789           {
790                   fg_color->red = XmMAX_SHORT;
791                   fg_color->green = XmMAX_SHORT;
792                   fg_color->blue = XmMAX_SHORT;
793           }
794 /*
795  * End Fix 4602
796  */
797 	}
798 
799 	if (sel_color)
800 	{
801 		color_value = bg_color->red;
802 		color_value += XmCOLOR_DARK_SEL_FACTOR *
803 			(XmMAX_SHORT - color_value) / 100;
804 		sel_color->red = color_value;
805 
806 		color_value = bg_color->green;
807 		color_value += XmCOLOR_DARK_SEL_FACTOR *
808 			(XmMAX_SHORT - color_value) / 100;
809 		sel_color->green = color_value;
810 
811 		color_value = bg_color->blue;
812 		color_value += XmCOLOR_DARK_SEL_FACTOR *
813 			(XmMAX_SHORT - color_value) / 100;
814 		sel_color->blue = color_value;
815 	}
816 
817 	if (bs_color)
818 	{
819 		color_value = bg_color->red;
820 		color_value += XmCOLOR_DARK_BS_FACTOR *
821 			(XmMAX_SHORT - color_value) / 100;
822 		bs_color->red = color_value;
823 
824 		color_value = bg_color->green;
825 		color_value += XmCOLOR_DARK_BS_FACTOR *
826 			(XmMAX_SHORT - color_value) / 100;
827 		bs_color->green = color_value;
828 
829 		color_value = bg_color->blue;
830 		color_value += XmCOLOR_DARK_BS_FACTOR *
831 			(XmMAX_SHORT - color_value) / 100;
832 		bs_color->blue = color_value;
833 	}
834 
835 	if (ts_color)
836 	{
837 		color_value = bg_color->red;
838 		color_value += XmCOLOR_DARK_TS_FACTOR *
839 			(XmMAX_SHORT - color_value) / 100;
840 		ts_color->red = color_value;
841 
842 		color_value = bg_color->green;
843 		color_value += XmCOLOR_DARK_TS_FACTOR *
844 			(XmMAX_SHORT - color_value) / 100;
845 		ts_color->green = color_value;
846 
847 		color_value = bg_color->blue;
848 		color_value += XmCOLOR_DARK_TS_FACTOR *
849 			(XmMAX_SHORT - color_value) / 100;
850 		ts_color->blue = color_value;
851 	}
852 }
853 
854 static void
CalculateColorsForMediumBackground(XColor * bg_color,XColor * fg_color,XColor * sel_color,XColor * ts_color,XColor * bs_color)855 CalculateColorsForMediumBackground(
856         XColor *bg_color,
857         XColor *fg_color,
858         XColor *sel_color,
859         XColor *ts_color,
860         XColor *bs_color )
861 {
862 	int brightness = Brightness(bg_color);
863 	int color_value, f;
864 
865 	if (brightness > XmFOREGROUND_THRESHOLD)
866 	{
867 		fg_color->red = 0;
868 		fg_color->green = 0;
869 		fg_color->blue = 0;
870 	}
871 	else
872 	{
873 		fg_color->red = XmMAX_SHORT;
874 		fg_color->green = XmMAX_SHORT;
875 		fg_color->blue = XmMAX_SHORT;
876 	}
877 
878 	if (sel_color)
879 	{
880 		f = XmCOLOR_LO_SEL_FACTOR + (brightness
881 			* ( XmCOLOR_HI_SEL_FACTOR - XmCOLOR_LO_SEL_FACTOR )
882 			/ XmMAX_SHORT );
883 
884 		color_value = bg_color->red;
885 		color_value -= (color_value * f) / 100;
886 		sel_color->red = color_value;
887 
888 		color_value = bg_color->green;
889 		color_value -= (color_value * f) / 100;
890 		sel_color->green = color_value;
891 
892 		color_value = bg_color->blue;
893 		color_value -= (color_value * f) / 100;
894 		sel_color->blue = color_value;
895 	}
896 
897 	if (bs_color)
898 	{
899 		f = XmCOLOR_LO_BS_FACTOR + (brightness
900 			* ( XmCOLOR_HI_BS_FACTOR - XmCOLOR_LO_BS_FACTOR )
901 			/ XmMAX_SHORT);
902 
903 		color_value = bg_color->red;
904 		color_value -= (color_value * f) / 100;
905 		bs_color->red = color_value;
906 
907 		color_value = bg_color->green;
908 		color_value -= (color_value * f) / 100;
909 		bs_color->green = color_value;
910 
911 		color_value = bg_color->blue;
912 		color_value -= (color_value * f) / 100;
913 		bs_color->blue = color_value;
914 	}
915 
916 	if (ts_color)
917 	{
918 		f = XmCOLOR_LO_TS_FACTOR + (brightness
919 			* ( XmCOLOR_HI_TS_FACTOR - XmCOLOR_LO_TS_FACTOR )
920 			/ XmMAX_SHORT);
921 
922 		color_value = bg_color->red;
923 		color_value += f * ( XmMAX_SHORT - color_value ) / 100;
924 		ts_color->red = color_value;
925 
926 		color_value = bg_color->green;
927 		color_value += f * ( XmMAX_SHORT - color_value ) / 100;
928 		ts_color->green = color_value;
929 
930 		color_value = bg_color->blue;
931 		color_value += f * ( XmMAX_SHORT - color_value ) / 100;
932 		ts_color->blue = color_value;
933 	}
934 }
935 
936 static void
CalculateColorsRGB(XColor * bg_color,XColor * fg_color,XColor * sel_color,XColor * ts_color,XColor * bs_color)937 CalculateColorsRGB(
938         XColor *bg_color,
939         XColor *fg_color,
940         XColor *sel_color,
941         XColor *ts_color,
942         XColor *bs_color )
943 {
944 	int brightness = Brightness(bg_color);
945 
946 	/* make sure DefaultThresholds are inited */
947 	if (!XmTHRESHOLDS_INITD)
948 	    	GetDefaultThresholdsForScreen(
949 			DefaultScreenOfDisplay(_XmGetDefaultDisplay()));
950 
951 	if (brightness < XmCOLOR_DARK_THRESHOLD)
952 		CalculateColorsForDarkBackground(bg_color, fg_color,
953 			sel_color, ts_color, bs_color);
954 	else if (brightness > XmCOLOR_LITE_THRESHOLD)
955 		CalculateColorsForLightBackground(bg_color, fg_color,
956 			sel_color, ts_color, bs_color);
957 	else
958 		CalculateColorsForMediumBackground(bg_color, fg_color,
959 			sel_color, ts_color, bs_color);
960 }
961 
962 
963 /*********************************************************************
964  *
965  *  GetColors
966  *
967  *********************************************************************/
968 static XmColorData *
GetColors(Screen * screen,Colormap color_map,Pixel background)969 GetColors(
970         Screen *screen,
971         Colormap color_map,
972         Pixel background )
973 {
974 	Display * display = DisplayOfScreen (screen);
975 	XmColorData *old_colors;
976 	XmColorData new_colors;
977 
978 
979 	new_colors.screen = screen;
980 	new_colors.color_map = color_map;
981 	new_colors.background.pixel = background;
982 
983 	if (_XmSearchColorCache(
984 		(XmLOOK_AT_SCREEN | XmLOOK_AT_CMAP | XmLOOK_AT_BACKGROUND),
985 			&new_colors, &old_colors)) {
986                /*
987 		* initialize the thresholds if the current color scheme
988 		* already matched what is in the cache and the thresholds
989 		* haven't already been initialized.
990                 */
991                 if (!XmTHRESHOLDS_INITD)
992 	            GetDefaultThresholdsForScreen(screen);
993 		return(old_colors);
994         }
995 
996 	XQueryColor (display, color_map, &(new_colors.background));
997 	new_colors.allocated = XmBACKGROUND;
998 
999 	/*
1000 	 * Just in case somebody looks at these before they're ready,
1001 	 * initialize them to a value that is always valid (for most
1002 	 * implementations of X).
1003 	 */
1004 	new_colors.foreground.pixel = 0;
1005 	new_colors.top_shadow.pixel = 0;
1006 	new_colors.top_shadow.pixel = 0;
1007 	new_colors.select.pixel = 0;
1008 
1009 	/*  Generate the foreground, top_shadow, and bottom_shadow based  */
1010 	/*  on the background                                             */
1011 
1012 	if (DefaultDepthOfScreen(screen) == 1)
1013 		SetMonochromeColors(&new_colors);
1014 	else
1015 	  {
1016 	      XmScreenColorProc screen_color_proc ;
1017 
1018 	      GetDefaultThresholdsForScreen(screen);
1019 
1020 	      /* look for the new per-Screen resource */
1021 	      screen_color_proc = _XmGetColorCalculationProc(screen);
1022 
1023 	      if (!screen_color_proc) {
1024 		  /* no new color proc set, use the old one */
1025 		  (*ColorRGBCalcProc)(&(new_colors.background),
1026 				      &(new_colors.foreground),
1027 				      &(new_colors.select),
1028 				      &(new_colors.top_shadow),
1029 				      &(new_colors.bottom_shadow));
1030 	      } else {
1031 		  /* call the application */
1032 		  (*screen_color_proc)(screen,
1033 				       &(new_colors.background),
1034 				       &(new_colors.foreground),
1035 				       &(new_colors.select),
1036 				       &(new_colors.top_shadow),
1037 				       &(new_colors.bottom_shadow));
1038 	      }
1039 	  }
1040 	return (_XmAddToColorCache(&new_colors));
1041 }
1042 
1043 
1044 
1045 /*********************************************************************
1046          Global API
1047  ********************************************************************/
1048 
1049 
1050 /* DEPRECATED in favor of the Screen resource XmNcolorcalculationProc
1051    that takes a Screen in argument (while colorProc doesn't) */
1052 XmColorProc
XmSetColorCalculation(XmColorProc proc)1053 XmSetColorCalculation(
1054         XmColorProc proc )
1055 {
1056 	XmColorProc a = ColorRGBCalcProc;
1057 
1058 	_XmProcessLock();
1059 	if (proc != NULL)
1060 		ColorRGBCalcProc = proc;
1061 	else
1062 		ColorRGBCalcProc = CalculateColorsRGB;
1063 
1064 	_XmProcessUnlock();
1065 	return(a);
1066 }
1067 
1068 /* DEPRECATED */
1069 XmColorProc
XmGetColorCalculation(void)1070 XmGetColorCalculation( void )
1071 {
1072 	return(ColorRGBCalcProc);
1073 }
1074 
1075 
1076 
1077 
1078 void
XmGetColors(Screen * screen,Colormap color_map,Pixel background,Pixel * foreground_ret,Pixel * top_shadow_ret,Pixel * bottom_shadow_ret,Pixel * select_ret)1079 XmGetColors(
1080         Screen *screen,
1081         Colormap color_map,
1082         Pixel background,
1083         Pixel *foreground_ret,
1084         Pixel *top_shadow_ret,
1085         Pixel *bottom_shadow_ret,
1086         Pixel *select_ret )
1087 {
1088 	XmColorData *cd;
1089 
1090         _XmDisplayToAppContext(DisplayOfScreen(screen));
1091         _XmAppLock(app);
1092 	_XmProcessLock();
1093 	cd = GetColors(screen, color_map, background);
1094 
1095 	if (foreground_ret)
1096 		*foreground_ret = AccessColorData(cd, XmFOREGROUND);
1097 	if (top_shadow_ret)
1098 		*top_shadow_ret = AccessColorData(cd, XmTOP_SHADOW);
1099 	if (bottom_shadow_ret)
1100 		*bottom_shadow_ret = AccessColorData(cd, XmBOTTOM_SHADOW);
1101 	if (select_ret)
1102 		*select_ret = AccessColorData(cd, XmSELECT);
1103 	_XmProcessUnlock();
1104 	_XmAppUnlock(app);
1105 }
1106 
1107 
1108 /*********************************************************************
1109  *
1110  *  XmeGetDefaultPixel
1111  *	Given the widget and the requested type of default, generate the
1112  *	default and store it in the value structure to be returned.
1113  *
1114  *********************************************************************/
1115 /*ARGSUSED*/
1116 void
XmeGetDefaultPixel(Widget widget,int type,int offset,XrmValue * value)1117 XmeGetDefaultPixel(
1118         Widget widget,
1119         int type,
1120         int offset,
1121         XrmValue *value )
1122 {
1123     Screen *screen;
1124     Colormap color_map;
1125     static Pixel new_value;
1126     XmColorData *color_data;
1127     Pixel background = 0 ;
1128     Widget parent;
1129 
1130     _XmWidgetToAppContext(widget);
1131 
1132     _XmAppLock(app);
1133     value->size = sizeof(new_value);
1134     value->addr = (char *) &new_value;
1135 
1136     if (!XtIsWidget(widget))
1137 	{
1138 	parent = widget->core.parent;
1139 	color_map = parent->core.colormap;
1140 
1141 	/*
1142 	 *  Skip this for the background case.  The background
1143 	 * field hasn't been inited yet but for the background
1144 	 * case it isn't needed.
1145 	 */
1146 
1147 	if (type != XmBACKGROUND)
1148 	    {
1149 	    if ((XmIsLabelGadget(widget)) ||
1150 		(XmIsArrowButtonGadget(widget)) ||
1151 		(XmIsSeparatorGadget(widget)))
1152 		XtVaGetValues(widget, XmNbackground, &background, NULL);
1153 	    else
1154 		{
1155 		/*
1156 		  This line should not be executed but this case does
1157 		  need to be handled.
1158 		  */
1159 		background = parent->core.background_pixel;
1160 		}
1161 	    }
1162 	}
1163     else
1164 	{
1165 	color_map = widget->core.colormap;
1166 	if(type != XmBACKGROUND)
1167 	    background = widget->core.background_pixel;
1168 	}
1169 
1170 
1171     screen = XtScreen(widget);
1172 
1173     if (type == XmBACKGROUND)
1174 	{
1175 	color_data = GetDefaultColors(screen, color_map);
1176 	}
1177     else
1178 	{
1179 	color_data = GetColors(screen, color_map, background);
1180 	}
1181 
1182     new_value = AccessColorData(color_data, type);
1183     _XmAppUnlock(app);
1184 }
1185 
1186 /************************************************************************
1187  *
1188  *  Dynamic defaulting color functions
1189  *
1190  ************************************************************************/
1191 
1192 void
_XmForegroundColorDefault(Widget widget,int offset,XrmValue * value)1193 _XmForegroundColorDefault(
1194         Widget widget,
1195         int offset,
1196         XrmValue *value )
1197 {
1198    XmeGetDefaultPixel (widget, XmFOREGROUND, offset, value);
1199 }
1200 
1201 void
_XmHighlightColorDefault(Widget widget,int offset,XrmValue * value)1202 _XmHighlightColorDefault(
1203         Widget widget,
1204         int offset,
1205         XrmValue *value )
1206 {
1207    XmeGetDefaultPixel (widget, XmFOREGROUND, offset, value);
1208 }
1209 
1210 void
_XmBackgroundColorDefault(Widget widget,int offset,XrmValue * value)1211 _XmBackgroundColorDefault(
1212         Widget widget,
1213         int offset,
1214         XrmValue *value )
1215 {
1216    XmeGetDefaultPixel (widget, XmBACKGROUND, offset, value);
1217 }
1218 
1219 void
_XmTopShadowColorDefault(Widget widget,int offset,XrmValue * value)1220 _XmTopShadowColorDefault(
1221         Widget widget,
1222         int offset,
1223         XrmValue *value )
1224 {
1225    XmeGetDefaultPixel (widget, XmTOP_SHADOW, offset, value);
1226 }
1227 
1228 void
_XmBottomShadowColorDefault(Widget widget,int offset,XrmValue * value)1229 _XmBottomShadowColorDefault(
1230         Widget widget,
1231         int offset,
1232         XrmValue *value )
1233 {
1234    XmeGetDefaultPixel (widget, XmBOTTOM_SHADOW, offset, value);
1235 }
1236 
1237 void
_XmSelectColorDefault(Widget widget,int offset,XrmValue * value)1238 _XmSelectColorDefault(
1239         Widget widget,
1240         int offset,
1241         XrmValue *value )
1242 {
1243    XmeGetDefaultPixel (widget, XmSELECT, offset, value);
1244 }
1245 
1246 #ifdef FIX_1381
1247 static
1248 unsigned int
FromColorToBlackAndWhite(char * col)1249 FromColorToBlackAndWhite(char *col)
1250 {
1251    unsigned long r, g, b, bw;
1252    char k[5];
1253    k[4] = '\0';
1254 
1255    memcpy(k, col, 4);
1256    r = strtoul(k, NULL, 16);
1257    memcpy(k, col + 4, 4);
1258    g = strtoul(k, NULL, 16);
1259    b = strtoul(col + 8, NULL, 16);
1260    bw = (0.3 * r + 0.59 * g + 0.11 * b);
1261    return (bw);
1262 }
1263 
1264 Pixmap
_XmConvertToBW(Widget w,Pixmap pm)1265 _XmConvertToBW(Widget w, Pixmap pm)
1266 {
1267    XpmImage im;
1268    int i = 0;
1269    unsigned int bw = 0, bw2 = 0;
1270    char *col = NULL, *col2 = NULL;
1271    Pixmap bw_pixmap = XmUNSPECIFIED_PIXMAP;
1272 #ifdef FIX_1500
1273    char *data_before = NULL, *data_after = NULL;
1274 #endif
1275 
1276    if (pm == XmUNSPECIFIED_PIXMAP)
1277 	   return bw_pixmap;
1278 
1279 #ifdef FIX_1500
1280    XpmCreateBufferFromPixmap(XtDisplay(w), &data_before, pm, 0, NULL);
1281 #endif
1282    XpmCreateXpmImageFromPixmap(XtDisplay(w), pm, 0, &im, NULL);
1283    if (im.ncolors > 0) {
1284 	   if (im.ncolors <= 2) {
1285 		   if (im.ncolors == 1) {
1286 			   col = strdup(im.colorTable[0].c_color);
1287 			   if (col[0] == '#') {
1288 				   bw = (FromColorToBlackAndWhite(col + 1) * 0.65);
1289 				   sprintf(im.colorTable[0].c_color, "#%04x%04x%04x", bw, bw, bw);
1290 			   }
1291 			   if (col)
1292 				   free(col);
1293 		   } else {
1294 			   col = im.colorTable[0].c_color;
1295 			   col2 = im.colorTable[1].c_color;
1296 			   if ((col[0] == '#') && (col2[0] == '#')) {
1297 				   bw = FromColorToBlackAndWhite(col + 1);
1298 				   bw2 = FromColorToBlackAndWhite(col2 + 1);
1299 				   if (bw >= bw2) {
1300 					   bw2 = bw2 + ((bw - bw2) * 0.65);
1301 					   sprintf(im.colorTable[1].c_color, "#%04x%04x%04x", bw2, bw2, bw2);
1302 				   } else {
1303 					   bw = bw + ((bw2 - bw) * 0.65);
1304 					   sprintf (im.colorTable[0].c_color, "#%04x%04x%04x", bw, bw, bw);
1305 				   }
1306 			   }
1307 		   }
1308 	   } else {
1309 		   char e[5];
1310 		   for (i = 0; i < im.ncolors; i++) {
1311 			   col = im.colorTable[i].c_color;
1312 			   if (col[0] == '#') {
1313 				   bw = FromColorToBlackAndWhite(col + 1);
1314 				   /* could be
1315 					sprintf(im.colorTable[i].c_color, "#%04x%04x%04x", bw, bw, bw);
1316 					Four lower lines is sprintf optimized version */
1317 				   sprintf(e, "%04x", bw);
1318 				   memcpy(col + 1, e, 4);
1319 				   memcpy(col + 5, e, 4);
1320 				   memcpy(col + 9, e, 4);
1321 			   }
1322 		   }
1323 	   }
1324    }
1325    XpmCreatePixmapFromXpmImage(XtDisplay(w), pm, &im, &bw_pixmap, 0, NULL);
1326 #ifdef FIX_1500
1327    if (bw_pixmap)
1328 	   XpmCreateBufferFromPixmap(XtDisplay(w), &data_after, bw_pixmap, 0, NULL);
1329 
1330    if (data_before && data_after && !strcmp(data_before, data_after))
1331 	   bw_pixmap = 0;
1332 
1333    if (data_before)
1334 	   XpmFree(data_before);
1335    if (data_after)
1336 	   XpmFree(data_after);
1337 #endif
1338    XpmFreeXpmImage(&im);
1339 
1340 #ifdef FIX_1505
1341    return (bw_pixmap) ? bw_pixmap : pm;
1342 #else
1343    return bw_pixmap;
1344 #endif
1345 }
1346 #endif
1347 
1348