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