/* $TOG: Color.c /main/13 1998/09/23 19:36:49 samborn $ */
/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* HISTORY
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/ShellP.h>
#include <Xm/ManagerP.h>
#include <Xm/PrimitiveP.h>
#include <Xm/XmP.h>
#include <Xm/XmosP.h> /* for bzero */
#include "ColorI.h"
#include "ImageCachI.h"
#include "MessagesI.h"
#include "ScreenI.h"
#include "XmI.h"
#ifdef FIX_1381
#include <Xm/XpmP.h>
#endif
#define FIX_1500
/* Warning and Error messages */
#define MESSAGE0 _XmMMsgVisual_0000
#define MESSAGE1 _XmMMsgVisual_0001
#define MESSAGE2 _XmMMsgVisual_0002
/******** Static Function Declarations ********/
static void GetDefaultThresholdsForScreen(
Screen *screen) ;
static XmColorData * GetDefaultColors(
Screen *screen,
Colormap color_map) ;
static Pixel GetBlackPixel(
Screen *screen,
Colormap colormap,
XColor blackcolor) ;
static Pixel GetWhitePixel(
Screen *screen,
Colormap colormap,
XColor whitecolor) ;
static void SetMonochromeColors(
XmColorData *colors) ;
static int Brightness(
XColor *color) ;
static void CalculateColorsForLightBackground(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color) ;
static void CalculateColorsForDarkBackground(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color) ;
static void CalculateColorsForMediumBackground(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color) ;
static void CalculateColorsRGB(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color) ;
static Pixel AccessColorData(
XmColorData *cd,
unsigned char which) ;
static XmColorData * GetColors(
Screen *screen,
Colormap color_map,
Pixel background) ;
#ifdef FIX_1381
static unsigned int FromColorToBlackAndWhite(
char *col) ;
#endif
/******** End Static Function Declarations ********/
/*
* GLOBAL VARIABLES
*
* These variables define the color cache.
*/
static int Set_Count=0, Set_Size=0;
static XmColorData *Color_Set=NULL;
/* Thresholds for brightness
above LITE threshold, LITE color model is used
below DARK threshold, DARK color model is be used
use STD color model in between */
static int XmCOLOR_LITE_THRESHOLD;
static int XmCOLOR_DARK_THRESHOLD;
static int XmFOREGROUND_THRESHOLD;
static Boolean XmTHRESHOLDS_INITD = FALSE;
/* DEPRECATED : use XmScreen resource now */
static XmColorProc ColorRGBCalcProc = CalculateColorsRGB;
static void
GetDefaultThresholdsForScreen( Screen *screen )
{
XmScreen xmScreen;
int default_light_threshold_spec;
int default_dark_threshold_spec;
int default_foreground_threshold_spec;
_XmProcessLock();
XmTHRESHOLDS_INITD = True;
_XmProcessUnlock();
xmScreen = (XmScreen) XmGetXmScreen(screen);
/* Get resources from the XmScreen */
default_light_threshold_spec = xmScreen->screen.lightThreshold;
default_dark_threshold_spec = xmScreen->screen.darkThreshold;
default_foreground_threshold_spec = xmScreen->screen.foregroundThreshold;
if ((default_light_threshold_spec <= 0) ||
(default_light_threshold_spec > 100))
default_light_threshold_spec = XmDEFAULT_LIGHT_THRESHOLD;
if ((default_dark_threshold_spec <= 0) ||
(default_dark_threshold_spec > 100))
default_dark_threshold_spec = XmDEFAULT_DARK_THRESHOLD;
if ((default_foreground_threshold_spec <= 0) ||
(default_foreground_threshold_spec > 100))
default_foreground_threshold_spec = XmDEFAULT_FOREGROUND_THRESHOLD;
_XmProcessLock();
XmCOLOR_LITE_THRESHOLD = default_light_threshold_spec * XmCOLOR_PERCENTILE;
XmCOLOR_DARK_THRESHOLD = default_dark_threshold_spec * XmCOLOR_PERCENTILE;
XmFOREGROUND_THRESHOLD = default_foreground_threshold_spec * XmCOLOR_PERCENTILE;
_XmProcessUnlock();
}
static XColor *GetDefaultBackgroundColor(Screen *screen, Colormap color_map)
{
XrmName names[2];
XrmClass classes[2];
XrmRepresentation rep;
XrmValue db_value;
static XColor color;
names[0] = XrmPermStringToQuark(XmNbackground);
names[1] = NULLQUARK;
classes[0] = XrmPermStringToQuark(XmCBackground);
classes[1] = NULLQUARK;
if (XrmQGetResource(XtScreenDatabase(screen), names, classes,
&rep, &db_value))
{
if (rep == XrmPermStringToQuark(XmRString)) {
if (!XParseColor(DisplayOfScreen(screen), color_map, db_value.addr,
&color)) return NULL;
}
else if (rep == XrmPermStringToQuark(XmRPixel)) {
color.pixel = *(Pixel *) db_value.addr;
XQueryColor(DisplayOfScreen(screen), color_map, &color);
}
}
else {
if (!XParseColor(DisplayOfScreen(screen), color_map, XmDEFAULT_BACKGROUND,
&color)) return NULL;
}
return &color;
}
static XmColorData *
GetDefaultColors(
Screen *screen,
Colormap color_map )
{
static XmColorData * default_set = NULL;
static int default_set_count = 0;
static int default_set_size = 0;
register int i;
XColor *color_def;
static Pixel background;
XrmValue fromVal;
XrmValue toVal;
XrmValue args[2];
Cardinal num_args;
String default_string = XtDefaultBackground;
XmColorData *result;
_XmProcessLock();
/* Look through a set of screen / background pairs to see */
/* if the default is already in the table. */
for (i = 0; i < default_set_count; i++)
{
if ((default_set[i].screen == screen) &&
(default_set[i].color_map == color_map))
{
result = default_set + i;
_XmProcessUnlock();
return result;
}
}
/* See if more space is needed in the array */
if (default_set == NULL)
{
default_set_size = 10;
default_set = (XmColorData *) XtRealloc((char *) default_set,
(sizeof(XmColorData) * default_set_size));
}
else if (default_set_count == default_set_size)
{
default_set_size += 10;
default_set = (XmColorData *) XtRealloc((char *) default_set,
sizeof(XmColorData) * default_set_size);
}
/* Find the background based on the depth of the screen */
if (DefaultDepthOfScreen(screen) == 1)
{
/*
* Fix for 4603 - Convert the string XtDefaultBackground into a Pixel
* value using the XToolkit converter. This converter
* will set this value to WhitePixelOfScreen if reverse
* video is not on, and to BlackPixelOfScreen if reverse
* video is on.
*/
args[0].addr = (XPointer) &screen;
args[0].size = sizeof(Screen*);
args[1].addr = (XPointer) &color_map;
args[1].size = sizeof(Colormap);
num_args = 2;
fromVal.addr = default_string;
fromVal.size = strlen(default_string);
toVal.addr = (XPointer) &background;
toVal.size = sizeof(Pixel);
if(!XtCallConverter(DisplayOfScreen(screen),XtCvtStringToPixel,
args, num_args, &fromVal, &toVal, NULL))
background = WhitePixelOfScreen(screen);
}
else
{
/* Parse out a color for the default background */
if ((color_def = GetDefaultBackgroundColor(screen,
color_map)) !=
NULL)
{
XmAllocColorProc aproc =
_XmGetColorAllocationProc(screen);
if (aproc == NULL)
aproc = DEFAULT_ALLOCCOLOR_PROC;
if ((*aproc)(DisplayOfScreen(screen), color_map,
color_def))
{
background = color_def->pixel;
}
else
{
XtWarning(MESSAGE1);
background = WhitePixelOfScreen(screen);
}
}
else
{
XtWarning(MESSAGE2);
background = WhitePixelOfScreen(screen);
}
}
/*
* Get the color data generated and save it in the next open
* slot in the default set array. default_set points to a subset
* of the data pointed to by color_set (defined in GetColors).
*/
default_set[default_set_count] =
*GetColors(screen, color_map, background);
default_set_count++;
result = default_set + (default_set_count - 1);
_XmProcessUnlock();
return result;
}
Boolean
_XmSearchColorCache(
unsigned int which,
XmColorData *values,
XmColorData **ret )
{
register int i;
/*
* Look through a set of screen, color_map, background triplets
* to see if these colors have already been generated.
*/
_XmProcessLock();
for (i = 0; i < Set_Count; i++) {
if ( (!(which & XmLOOK_AT_SCREEN) ||
((Color_Set + i)->screen == values->screen))
&&
(!(which & XmLOOK_AT_CMAP) ||
((Color_Set + i)->color_map == values->color_map))
&&
(!(which & XmLOOK_AT_BACKGROUND) ||
(((Color_Set + i)->allocated & XmBACKGROUND) &&
((Color_Set + i)->background.pixel ==
values->background.pixel)))
&&
(!(which & XmLOOK_AT_FOREGROUND) ||
(((Color_Set + i)->allocated & XmFOREGROUND) &&
((Color_Set + i)->foreground.pixel ==
values->foreground.pixel)))
&&
(!(which & XmLOOK_AT_TOP_SHADOW) ||
(((Color_Set + i)->allocated & XmTOP_SHADOW) &&
((Color_Set + i)->top_shadow.pixel ==
values->top_shadow.pixel)))
&&
(!(which & XmLOOK_AT_BOTTOM_SHADOW) ||
(((Color_Set + i)->allocated & XmBOTTOM_SHADOW) &&
((Color_Set+ i)->bottom_shadow.pixel ==
values->bottom_shadow.pixel)))
&&
(!(which & XmLOOK_AT_SELECT) ||
(((Color_Set + i)->allocated & XmSELECT) &&
((Color_Set + i)->select.pixel ==
values->select.pixel))))
{
*ret = (Color_Set + i);
_XmProcessUnlock();
return (TRUE);
}
}
*ret = NULL;
_XmProcessUnlock();
return (FALSE);
}
XmColorData *
_XmAddToColorCache(
XmColorData *new_rec )
{
XmColorData *result;
/* See if more space is needed */
_XmProcessLock();
if (Set_Count == Set_Size)
{
Set_Size += 10;
Color_Set = (XmColorData *)XtRealloc((char *) Color_Set,
sizeof(XmColorData) * Set_Size);
}
*(Color_Set + Set_Count) = *new_rec;
Set_Count++;
result = Color_Set + (Set_Count - 1);
_XmProcessUnlock();
return result;
}
static Pixel
GetBlackPixel(
Screen *screen,
Colormap colormap,
XColor blackcolor )
{
Pixel p;
XmAllocColorProc aproc = _XmGetColorAllocationProc(screen);
if (aproc == NULL)
aproc = DEFAULT_ALLOCCOLOR_PROC;
blackcolor.red = 0;
blackcolor.green = 0;
blackcolor.blue = 0;
if (colormap == DefaultColormapOfScreen(screen))
p = blackcolor.pixel = BlackPixelOfScreen(screen);
else if ((*aproc)(screen->display, colormap, &blackcolor))
p = blackcolor.pixel;
else
p = blackcolor.pixel = BlackPixelOfScreen(screen); /* fallback pixel */
return (p);
}
static Pixel
GetWhitePixel(
Screen *screen,
Colormap colormap,
XColor whitecolor )
{
Pixel p;
XmAllocColorProc aproc = _XmGetColorAllocationProc(screen);
if (aproc == NULL)
aproc = DEFAULT_ALLOCCOLOR_PROC;
whitecolor.red = XmMAX_SHORT;
whitecolor.green = XmMAX_SHORT;
whitecolor.blue = XmMAX_SHORT;
if (colormap == DefaultColormapOfScreen(screen))
p = whitecolor.pixel = WhitePixelOfScreen(screen);
else if ((*aproc)(screen->display, colormap, &whitecolor))
p = whitecolor.pixel;
else
p = whitecolor.pixel = WhitePixelOfScreen(screen); /* fallback pixel */
return (p);
}
static Pixel
AccessColorData(
XmColorData *cd,
unsigned char which )
{
Pixel p;
XmAllocColorProc aproc = _XmGetColorAllocationProc(cd->screen);
if (aproc == NULL)
aproc = DEFAULT_ALLOCCOLOR_PROC;
switch(which) {
case XmBACKGROUND:
if (!(cd->allocated & which) &&
((*aproc)(cd->screen->display,
cd->color_map, &(cd->background)) == 0)) {
if (Brightness(&(cd->background))
< XmFOREGROUND_THRESHOLD )
cd->background.pixel = GetBlackPixel(cd->screen,
cd->color_map,
cd->background);
else
cd->background.pixel = GetWhitePixel(cd->screen,
cd->color_map,
cd->background);
XQueryColor(cd->screen->display, cd->color_map,
&(cd->background));
}
p = cd->background.pixel;
cd->allocated |= which;
break;
case XmFOREGROUND:
if (!(cd->allocated & which) &&
((*aproc)(cd->screen->display,
cd->color_map, &(cd->foreground)) == 0 ))
{
if (Brightness(&(cd->background))
< XmFOREGROUND_THRESHOLD )
cd->foreground.pixel = GetWhitePixel(cd->screen,
cd->color_map,
cd->foreground);
else
cd->foreground.pixel = GetBlackPixel(cd->screen,
cd->color_map,
cd->foreground);
XQueryColor(cd->screen->display, cd->color_map,
&(cd->foreground));
}
p = cd->foreground.pixel;
cd->allocated |= which;
break;
case XmTOP_SHADOW:
if (!(cd->allocated & which) &&
((*aproc)(cd->screen->display,
cd->color_map, &(cd->top_shadow)) == 0))
{
if (Brightness(&(cd->background))
> XmCOLOR_LITE_THRESHOLD)
cd->top_shadow.pixel =
GetBlackPixel(cd->screen, cd->color_map,
cd->top_shadow);
else
cd->top_shadow.pixel =
GetWhitePixel(cd->screen, cd->color_map,
cd->top_shadow);
XQueryColor(cd->screen->display, cd->color_map,
&(cd->top_shadow));
}
p = cd->top_shadow.pixel;
cd->allocated |= which;
break;
case XmBOTTOM_SHADOW:
if (!(cd->allocated & which) &&
((*aproc)(cd->screen->display,
cd->color_map, &(cd->bottom_shadow)) == 0))
{
if (Brightness(&(cd->background))
< XmCOLOR_DARK_THRESHOLD)
cd->bottom_shadow.pixel =
GetWhitePixel(cd->screen, cd->color_map,
cd->bottom_shadow);
else
cd->bottom_shadow.pixel =
GetBlackPixel(cd->screen, cd->color_map,
cd->bottom_shadow);
XQueryColor(cd->screen->display, cd->color_map,
&(cd->bottom_shadow));
}
p = cd->bottom_shadow.pixel;
cd->allocated |= which;
break;
case XmSELECT:
if (!(cd->allocated & which) &&
((*aproc)(cd->screen->display,
cd->color_map, &(cd->select)) == 0))
{
if (Brightness(&(cd->background))
< XmFOREGROUND_THRESHOLD)
cd->select.pixel = GetWhitePixel(cd->screen,
cd->color_map,
cd->select);
else
cd->select.pixel = GetBlackPixel(cd->screen,
cd->color_map,
cd->select);
XQueryColor(cd->screen->display, cd->color_map,
&(cd->select));
}
p = cd->select.pixel;
cd->allocated |= which;
break;
default:
XtWarning(MESSAGE0);
p = GetBlackPixel(cd->screen, cd->color_map, cd->background);
break;
}
return(p);
}
static void
SetMonochromeColors(
XmColorData *colors )
{
Screen *screen = colors->screen;
Pixel background = colors->background.pixel;
if (background == BlackPixelOfScreen(screen))
{
colors->foreground.pixel = WhitePixelOfScreen (screen);
colors->foreground.red = colors->foreground.green =
colors->foreground.blue = XmMAX_SHORT;
colors->bottom_shadow.pixel = WhitePixelOfScreen(screen);
colors->bottom_shadow.red = colors->bottom_shadow.green =
colors->bottom_shadow.blue = XmMAX_SHORT;
colors->select.pixel = WhitePixelOfScreen(screen);
colors->select.red = colors->select.green =
colors->select.blue = XmMAX_SHORT;
colors->top_shadow.pixel = BlackPixelOfScreen(screen);
colors->top_shadow.red = colors->top_shadow.green =
colors->top_shadow.blue = 0;
}
else if (background == WhitePixelOfScreen(screen))
{
colors->foreground.pixel = BlackPixelOfScreen(screen);
colors->foreground.red = colors->foreground.green =
colors->foreground.blue = 0;
colors->top_shadow.pixel = WhitePixelOfScreen(screen);
colors->top_shadow.red = colors->top_shadow.green =
colors->top_shadow.blue = XmMAX_SHORT;
colors->bottom_shadow.pixel = BlackPixelOfScreen(screen);
colors->bottom_shadow.red = colors->bottom_shadow.green =
colors->bottom_shadow.blue = 0;
colors->select.pixel = BlackPixelOfScreen(screen);
colors->select.red = colors->select.green =
colors->select.blue = 0;
}
colors->allocated |= (XmFOREGROUND | XmTOP_SHADOW
| XmBOTTOM_SHADOW | XmSELECT);
}
static int
Brightness(
XColor *color )
{
int brightness;
int intensity;
int light;
int luminosity, maxprimary, minprimary;
int red = color->red;
int green = color->green;
int blue = color->blue;
intensity = (red + green + blue) / 3;
/*
* The casting nonsense below is to try to control the point at
* the truncation occurs.
*/
luminosity = (int) ((XmRED_LUMINOSITY * (float) red)
+ (XmGREEN_LUMINOSITY * (float) green)
+ (XmBLUE_LUMINOSITY * (float) blue));
maxprimary = ( (red > green) ?
( (red > blue) ? red : blue ) :
( (green > blue) ? green : blue ) );
minprimary = ( (red < green) ?
( (red < blue) ? red : blue ) :
( (green < blue) ? green : blue ) );
light = (minprimary + maxprimary) / 2;
brightness = ( (intensity * XmINTENSITY_FACTOR) +
(light * XmLIGHT_FACTOR) +
(luminosity * XmLUMINOSITY_FACTOR) ) / 100;
return(brightness);
}
static void
CalculateColorsForLightBackground(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color )
{
int brightness = Brightness(bg_color);
int color_value;
if (fg_color)
{
/*
* Fix for 4602 - Compare the brightness with the foreground threshold.
* If its larger, make the foreground color black.
* Otherwise, make it white.
*/
if (brightness > XmFOREGROUND_THRESHOLD)
{
fg_color->red = 0;
fg_color->green = 0;
fg_color->blue = 0;
}
else
{
fg_color->red = XmMAX_SHORT;
fg_color->green = XmMAX_SHORT;
fg_color->blue = XmMAX_SHORT;
}
/*
* End Fix 4602
*/
}
if (sel_color)
{
color_value = bg_color->red;
color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
sel_color->red = color_value;
color_value = bg_color->green;
color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
sel_color->green = color_value;
color_value = bg_color->blue;
color_value -= (color_value * XmCOLOR_LITE_SEL_FACTOR) / 100;
sel_color->blue = color_value;
}
if (bs_color)
{
color_value = bg_color->red;
color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
bs_color->red = color_value;
color_value = bg_color->green;
color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
bs_color->green = color_value;
color_value = bg_color->blue;
color_value -= (color_value * XmCOLOR_LITE_BS_FACTOR) / 100;
bs_color->blue = color_value;
}
if (ts_color)
{
color_value = bg_color->red;
color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
ts_color->red = color_value;
color_value = bg_color->green;
color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
ts_color->green = color_value;
color_value = bg_color->blue;
color_value -= (color_value * XmCOLOR_LITE_TS_FACTOR) / 100;
ts_color->blue = color_value;
}
}
static void
CalculateColorsForDarkBackground(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color )
{
int brightness = Brightness(bg_color);
int color_value;
if (fg_color)
{
/*
* Fix for 4602 - Compare the brightness with the foreground threshold.
* If its larger, make the foreground color black.
* Otherwise, make it white.
*/
if (brightness > XmFOREGROUND_THRESHOLD)
{
fg_color->red = 0;
fg_color->green = 0;
fg_color->blue = 0;
}
else
{
fg_color->red = XmMAX_SHORT;
fg_color->green = XmMAX_SHORT;
fg_color->blue = XmMAX_SHORT;
}
/*
* End Fix 4602
*/
}
if (sel_color)
{
color_value = bg_color->red;
color_value += XmCOLOR_DARK_SEL_FACTOR *
(XmMAX_SHORT - color_value) / 100;
sel_color->red = color_value;
color_value = bg_color->green;
color_value += XmCOLOR_DARK_SEL_FACTOR *
(XmMAX_SHORT - color_value) / 100;
sel_color->green = color_value;
color_value = bg_color->blue;
color_value += XmCOLOR_DARK_SEL_FACTOR *
(XmMAX_SHORT - color_value) / 100;
sel_color->blue = color_value;
}
if (bs_color)
{
color_value = bg_color->red;
color_value += XmCOLOR_DARK_BS_FACTOR *
(XmMAX_SHORT - color_value) / 100;
bs_color->red = color_value;
color_value = bg_color->green;
color_value += XmCOLOR_DARK_BS_FACTOR *
(XmMAX_SHORT - color_value) / 100;
bs_color->green = color_value;
color_value = bg_color->blue;
color_value += XmCOLOR_DARK_BS_FACTOR *
(XmMAX_SHORT - color_value) / 100;
bs_color->blue = color_value;
}
if (ts_color)
{
color_value = bg_color->red;
color_value += XmCOLOR_DARK_TS_FACTOR *
(XmMAX_SHORT - color_value) / 100;
ts_color->red = color_value;
color_value = bg_color->green;
color_value += XmCOLOR_DARK_TS_FACTOR *
(XmMAX_SHORT - color_value) / 100;
ts_color->green = color_value;
color_value = bg_color->blue;
color_value += XmCOLOR_DARK_TS_FACTOR *
(XmMAX_SHORT - color_value) / 100;
ts_color->blue = color_value;
}
}
static void
CalculateColorsForMediumBackground(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color )
{
int brightness = Brightness(bg_color);
int color_value, f;
if (brightness > XmFOREGROUND_THRESHOLD)
{
fg_color->red = 0;
fg_color->green = 0;
fg_color->blue = 0;
}
else
{
fg_color->red = XmMAX_SHORT;
fg_color->green = XmMAX_SHORT;
fg_color->blue = XmMAX_SHORT;
}
if (sel_color)
{
f = XmCOLOR_LO_SEL_FACTOR + (brightness
* ( XmCOLOR_HI_SEL_FACTOR - XmCOLOR_LO_SEL_FACTOR )
/ XmMAX_SHORT );
color_value = bg_color->red;
color_value -= (color_value * f) / 100;
sel_color->red = color_value;
color_value = bg_color->green;
color_value -= (color_value * f) / 100;
sel_color->green = color_value;
color_value = bg_color->blue;
color_value -= (color_value * f) / 100;
sel_color->blue = color_value;
}
if (bs_color)
{
f = XmCOLOR_LO_BS_FACTOR + (brightness
* ( XmCOLOR_HI_BS_FACTOR - XmCOLOR_LO_BS_FACTOR )
/ XmMAX_SHORT);
color_value = bg_color->red;
color_value -= (color_value * f) / 100;
bs_color->red = color_value;
color_value = bg_color->green;
color_value -= (color_value * f) / 100;
bs_color->green = color_value;
color_value = bg_color->blue;
color_value -= (color_value * f) / 100;
bs_color->blue = color_value;
}
if (ts_color)
{
f = XmCOLOR_LO_TS_FACTOR + (brightness
* ( XmCOLOR_HI_TS_FACTOR - XmCOLOR_LO_TS_FACTOR )
/ XmMAX_SHORT);
color_value = bg_color->red;
color_value += f * ( XmMAX_SHORT - color_value ) / 100;
ts_color->red = color_value;
color_value = bg_color->green;
color_value += f * ( XmMAX_SHORT - color_value ) / 100;
ts_color->green = color_value;
color_value = bg_color->blue;
color_value += f * ( XmMAX_SHORT - color_value ) / 100;
ts_color->blue = color_value;
}
}
static void
CalculateColorsRGB(
XColor *bg_color,
XColor *fg_color,
XColor *sel_color,
XColor *ts_color,
XColor *bs_color )
{
int brightness = Brightness(bg_color);
/* make sure DefaultThresholds are inited */
if (!XmTHRESHOLDS_INITD)
GetDefaultThresholdsForScreen(
DefaultScreenOfDisplay(_XmGetDefaultDisplay()));
if (brightness < XmCOLOR_DARK_THRESHOLD)
CalculateColorsForDarkBackground(bg_color, fg_color,
sel_color, ts_color, bs_color);
else if (brightness > XmCOLOR_LITE_THRESHOLD)
CalculateColorsForLightBackground(bg_color, fg_color,
sel_color, ts_color, bs_color);
else
CalculateColorsForMediumBackground(bg_color, fg_color,
sel_color, ts_color, bs_color);
}
/*********************************************************************
*
* GetColors
*
*********************************************************************/
static XmColorData *
GetColors(
Screen *screen,
Colormap color_map,
Pixel background )
{
Display * display = DisplayOfScreen (screen);
XmColorData *old_colors;
XmColorData new_colors;
new_colors.screen = screen;
new_colors.color_map = color_map;
new_colors.background.pixel = background;
if (_XmSearchColorCache(
(XmLOOK_AT_SCREEN | XmLOOK_AT_CMAP | XmLOOK_AT_BACKGROUND),
&new_colors, &old_colors)) {
/*
* initialize the thresholds if the current color scheme
* already matched what is in the cache and the thresholds
* haven't already been initialized.
*/
if (!XmTHRESHOLDS_INITD)
GetDefaultThresholdsForScreen(screen);
return(old_colors);
}
XQueryColor (display, color_map, &(new_colors.background));
new_colors.allocated = XmBACKGROUND;
/*
* Just in case somebody looks at these before they're ready,
* initialize them to a value that is always valid (for most
* implementations of X).
*/
new_colors.foreground.pixel = new_colors.top_shadow.pixel =
new_colors.top_shadow.pixel = new_colors.select.pixel = 0;
/* Generate the foreground, top_shadow, and bottom_shadow based */
/* on the background */
if (DefaultDepthOfScreen(screen) == 1)
SetMonochromeColors(&new_colors);
else
{
XmScreenColorProc screen_color_proc ;
GetDefaultThresholdsForScreen(screen);
/* look for the new per-Screen resource */
screen_color_proc = _XmGetColorCalculationProc(screen);
if (!screen_color_proc) {
/* no new color proc set, use the old one */
(*ColorRGBCalcProc)(&(new_colors.background),
&(new_colors.foreground),
&(new_colors.select),
&(new_colors.top_shadow),
&(new_colors.bottom_shadow));
} else {
/* call the application */
(*screen_color_proc)(screen,
&(new_colors.background),
&(new_colors.foreground),
&(new_colors.select),
&(new_colors.top_shadow),
&(new_colors.bottom_shadow));
}
}
return (_XmAddToColorCache(&new_colors));
}
/*********************************************************************
Global API
********************************************************************/
/* DEPRECATED in favor of the Screen resource XmNcolorcalculationProc
that takes a Screen in argument (while colorProc doesn't) */
XmColorProc
XmSetColorCalculation(
XmColorProc proc )
{
XmColorProc a = ColorRGBCalcProc;
_XmProcessLock();
if (proc != NULL)
ColorRGBCalcProc = proc;
else
ColorRGBCalcProc = CalculateColorsRGB;
_XmProcessUnlock();
return(a);
}
/* DEPRECATED */
XmColorProc
XmGetColorCalculation( void )
{
return(ColorRGBCalcProc);
}
void
XmGetColors(
Screen *screen,
Colormap color_map,
Pixel background,
Pixel *foreground_ret,
Pixel *top_shadow_ret,
Pixel *bottom_shadow_ret,
Pixel *select_ret )
{
XmColorData *cd;
_XmDisplayToAppContext(DisplayOfScreen(screen));
_XmAppLock(app);
_XmProcessLock();
cd = GetColors(screen, color_map, background);
if (foreground_ret)
*foreground_ret = AccessColorData(cd, XmFOREGROUND);
if (top_shadow_ret)
*top_shadow_ret = AccessColorData(cd, XmTOP_SHADOW);
if (bottom_shadow_ret)
*bottom_shadow_ret = AccessColorData(cd, XmBOTTOM_SHADOW);
if (select_ret)
*select_ret = AccessColorData(cd, XmSELECT);
_XmProcessUnlock();
_XmAppUnlock(app);
}
/*********************************************************************
*
* XmeGetDefaultPixel
* Given the widget and the requested type of default, generate the
* default and store it in the value structure to be returned.
*
*********************************************************************/
/*ARGSUSED*/
void
XmeGetDefaultPixel(
Widget widget,
int type,
int offset,
XrmValue *value )
{
Screen *screen;
Colormap color_map;
static Pixel new_value;
XmColorData *color_data;
Pixel background = 0 ;
Widget parent;
_XmWidgetToAppContext(widget);
_XmAppLock(app);
value->size = sizeof(new_value);
value->addr = (char *) &new_value;
if (!XtIsWidget(widget))
{
parent = widget->core.parent;
color_map = parent->core.colormap;
/*
* Skip this for the background case. The background
* field hasn't been inited yet but for the background
* case it isn't needed.
*/
if (type != XmBACKGROUND)
{
if ((XmIsLabelGadget(widget)) ||
(XmIsArrowButtonGadget(widget)) ||
(XmIsSeparatorGadget(widget)))
XtVaGetValues(widget, XmNbackground, &background, NULL);
else
{
/*
This line should not be executed but this case does
need to be handled.
*/
background = parent->core.background_pixel;
}
}
}
else
{
color_map = widget->core.colormap;
if(type != XmBACKGROUND)
background = widget->core.background_pixel;
}
screen = XtScreen(widget);
if (type == XmBACKGROUND)
{
color_data = GetDefaultColors(screen, color_map);
}
else
{
color_data = GetColors(screen, color_map, background);
}
new_value = AccessColorData(color_data, type);
_XmAppUnlock(app);
}
/************************************************************************
*
* Dynamic defaulting color functions
*
************************************************************************/
void
_XmForegroundColorDefault(
Widget widget,
int offset,
XrmValue *value )
{
XmeGetDefaultPixel (widget, XmFOREGROUND, offset, value);
}
void
_XmHighlightColorDefault(
Widget widget,
int offset,
XrmValue *value )
{
XmeGetDefaultPixel (widget, XmFOREGROUND, offset, value);
}
void
_XmBackgroundColorDefault(
Widget widget,
int offset,
XrmValue *value )
{
XmeGetDefaultPixel (widget, XmBACKGROUND, offset, value);
}
void
_XmTopShadowColorDefault(
Widget widget,
int offset,
XrmValue *value )
{
XmeGetDefaultPixel (widget, XmTOP_SHADOW, offset, value);
}
void
_XmBottomShadowColorDefault(
Widget widget,
int offset,
XrmValue *value )
{
XmeGetDefaultPixel (widget, XmBOTTOM_SHADOW, offset, value);
}
void
_XmSelectColorDefault(
Widget widget,
int offset,
XrmValue *value )
{
XmeGetDefaultPixel (widget, XmSELECT, offset, value);
}
#ifdef FIX_1381
static
unsigned int
FromColorToBlackAndWhite(char *col)
{
unsigned long r, g, b, bw;
char k[5];
k[4] = '\0';
memcpy(k, col, 4);
r = strtoul(k, NULL, 16);
memcpy(k, col + 4, 4);
g = strtoul(k, NULL, 16);
b = strtoul(col + 8, NULL, 16);
bw = (0.3 * r + 0.59 * g + 0.11 * b);
return (bw);
}
Pixmap
_XmConvertToBW(Widget w, Pixmap pm)
{
XpmImage im;
int i = 0;
unsigned int bw = 0, bw2 = 0;
char *col = NULL, *col2 = NULL;
Pixmap bw_pixmap = XmUNSPECIFIED_PIXMAP;
#ifdef FIX_1500
char *data_before = NULL, *data_after = NULL;
#endif
if (pm == XmUNSPECIFIED_PIXMAP)
return bw_pixmap;
#ifdef FIX_1500
XpmCreateBufferFromPixmap(XtDisplay(w), &data_before, pm, 0, NULL);
#endif
XpmCreateXpmImageFromPixmap(XtDisplay(w), pm, 0, &im, NULL);
if (im.ncolors > 0) {
if (im.ncolors <= 2) {
if (im.ncolors == 1) {
col = strdup(im.colorTable[0].c_color);
if (col[0] == '#') {
bw = (FromColorToBlackAndWhite(col + 1) * 0.65);
sprintf(im.colorTable[0].c_color, "#%04x%04x%04x", bw, bw, bw);
}
if (col)
free(col);
} else {
col = im.colorTable[0].c_color;
col2 = im.colorTable[1].c_color;
if ((col[0] == '#') && (col2[0] == '#')) {
bw = FromColorToBlackAndWhite(col + 1);
bw2 = FromColorToBlackAndWhite(col2 + 1);
if (bw >= bw2) {
bw2 = bw2 + ((bw - bw2) * 0.65);
sprintf(im.colorTable[1].c_color, "#%04x%04x%04x", bw2, bw2, bw2);
} else {
bw = bw + ((bw2 - bw) * 0.65);
sprintf (im.colorTable[0].c_color, "#%04x%04x%04x", bw, bw, bw);
}
}
}
} else {
char e[5];
for (i = 0; i < im.ncolors; i++) {
col = im.colorTable[i].c_color;
if (col[0] == '#') {
bw = FromColorToBlackAndWhite(col + 1);
/* could be
sprintf(im.colorTable[i].c_color, "#%04x%04x%04x", bw, bw, bw);
Four lower lines is sprintf optimized version */
sprintf(e, "%04x", bw);
memcpy(col + 1, e, 4);
memcpy(col + 5, e, 4);
memcpy(col + 9, e, 4);
}
}
}
}
XpmCreatePixmapFromXpmImage(XtDisplay(w), pm, &im, &bw_pixmap, 0, NULL);
#ifdef FIX_1500
if (bw_pixmap)
XpmCreateBufferFromPixmap(XtDisplay(w), &data_after, bw_pixmap, 0, NULL);
if (data_before && data_after && !strcmp(data_before, data_after))
bw_pixmap = 0;
if (data_before)
XpmFree(data_before);
if (data_after)
XpmFree(data_after);
#endif
XpmFreeXpmImage(&im);
#ifdef FIX_1505
return (bw_pixmap) ? bw_pixmap : pm;
#else
return bw_pixmap;
#endif
}
#endif