/*
 * Copyright (C) 1989-95 GROUPE BULL 
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions: 
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software. 
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 *
 * Except as contained in this notice, the name of GROUPE BULL shall not be used
 * in advertising or otherwise to promote the sale, use or other dealings in
 * this Software without prior written authorization from GROUPE BULL. 
 */

/*****************************************************************************\
* rgb.c:                                                                      *
*                                                                             *
*  XPM library                                                                *
*  Rgb file utilities                                                         *
*                                                                             *
*  Developed by Arnaud Le Hors                                                *
\*****************************************************************************/

/*
 * The code related to FOR_MSW has been added by HeDu
 * (hedu@cul-ipn.uni-kiel.de) 4/94 
 */

/*
 * Part of this code has been taken from the ppmtoxpm.c file written by Mark
 * W. Snitily but has been modified for my special need 
 */

#include "xpmP.h"
#include <ctype.h>
#if defined(SYSV) || defined(SVR4) || defined(VMS)
#include <string.h>
#else
#include <strings.h>
#endif

#ifndef FOR_MSW			/* normal part first, MSW part at the end,
				 * (huge ifdef!) */
/*
 * Read a rgb text file.  It stores the rgb values (0->65535) and the rgb
 * mnemonics (malloc'ed) into the "rgbn" array.  Returns the number of
 * entries stored. 
 */
int
xpmReadRgbNames(rgb_fname, rgbn)
char *rgb_fname;
xpmRgbName rgbn[];

{
 FILE *rgbf;
 int n, items, red, green, blue;
 char line[512], name[512], *rgbname, *s1, *s2;
 xpmRgbName *rgb;

 /* Open the rgb text file.  Abort if error. */
 if ((rgbf = fopen(rgb_fname, "r")) == NULL)
  return 0;

 /* Loop reading each line in the file. */
 n = 0;
 rgb = rgbn;
 /* Quit if rgb text file has too many entries. */
 while (fgets(line, sizeof(line), rgbf) && n < MAX_RGBNAMES)
 {

  /* Skip silently if line is bad. */
  items = sscanf(line, "%d %d %d %[^\n]\n", &red, &green, &blue, name);
  if (items != 4)
   continue;

  /*
   * Make sure rgb values are within 0->255 range. Skip silently if bad. 
   */
  if (red < 0 || red > 0xFF ||
      green < 0 || green > 0xFF ||
      blue < 0 || blue > 0xFF)
   continue;

  /* Allocate memory for ascii name. If error give up here. */
  if (!(rgbname = (char *) XpmMalloc(strlen(name) + 1)))
   break;

  /* Copy string to ascii name and lowercase it. */
  for (s1 = name, s2 = rgbname; *s1; s1++)
   *s2++ = tolower(*s1);
  *s2 = '\0';

  /* Save the rgb values and ascii name in the array. */
  rgb->r = red * 257;		/* 65535/255 = 257 */
  rgb->g = green * 257;
  rgb->b = blue * 257;
  rgb->name = rgbname;
  rgb++;
  n++;
 }

 fclose(rgbf);

 /* Return the number of read rgb names. */
 return n < 0 ? 0 : n;
}

/*
 * Return the color name corresponding to the given rgb values 
 */
char *
xpmGetRgbName(rgbn, rgbn_max, red, green, blue)
xpmRgbName rgbn[];		/* rgb mnemonics from rgb text file */
int rgbn_max;			/* number of rgb mnemonics in table */
int red, green, blue;		/* rgb values */

{
 int i;
 xpmRgbName *rgb;

 /*
  * Just perform a dumb linear search over the rgb values of the color
  * mnemonics.  One could speed things up by sorting the rgb values and using
  * a binary search, or building a hash table, etc... 
  */
 for (i = 0, rgb = rgbn; i < rgbn_max; i++, rgb++)
  if (red == rgb->r && green == rgb->g && blue == rgb->b)
   return rgb->name;

 /* if not found return NULL */
 return NULL;
}

/*
 * Free the strings which have been malloc'ed in xpmReadRgbNames 
 */
void
xpmFreeRgbNames(rgbn, rgbn_max)
xpmRgbName rgbn[];
int rgbn_max;

{
 int i;
 xpmRgbName *rgb;

 for (i = 0, rgb = rgbn; i < rgbn_max; i++, rgb++)
  XpmFree(rgb->name);
}

#else				/* here comes the MSW part, the second part
				 * of the  huge ifdef */

#include "rgbtab.h"		/* hard coded rgb.txt table */

int
xpmReadRgbNames(rgb_fname, rgbn)
char *rgb_fname;
xpmRgbName rgbn[];
{
 /*
  * check for consistency??? table has to be sorted for calls on strcasecmp 
  */
 return (numTheRGBRecords);
}

/*
 * MSW rgb values are made from 3 BYTEs, this is different from X XColor.red,
 * which has something like #0303 for one color 
 */
char *
xpmGetRgbName(rgbn, rgbn_max, red, green, blue)
xpmRgbName rgbn[];		/* rgb mnemonics from rgb text file not used */
int rgbn_max;			/* not used */
int red, green, blue;		/* rgb values */

{
 int i;
 unsigned long rgbVal;

 i = 0;
 while (i < numTheRGBRecords)
 {
  rgbVal = theRGBRecords[i].rgb;
  if (GetRValue(rgbVal) == red &&
      GetGValue(rgbVal) == green &&
      GetBValue(rgbVal) == blue)
   return (theRGBRecords[i].name);
  i++;
 }
 return (NULL);
}

/* used in XParseColor in simx.c */
int
xpmGetRGBfromName(inname, r, g, b)
char *inname;
int *r, *g, *b;
{
 int left, right, middle;
 int cmp;
 unsigned long rgbVal;
 char *name;
 char *grey, *p;

 name = strdup(inname);

 /*
  * the table in rgbtab.c has no names with spaces, and no grey, but a lot of
  * gray 
  */
 /* so first extract ' ' */
 while (p = strchr(name, ' '))
 {
  while (*(p))
  {				/* till eof of string */
   *p = *(p + 1);		/* copy to the left */
   p++;
  }
 }
 /* fold to lower case */
 p = name;
 while (*p)
 {
  *p = tolower(*p);
  p++;
 }

 /*
  * substitute Grey with Gray, else rgbtab.h would have more than 100
  * 'duplicate' entries 
  */
 if (grey = strstr(name, "grey"))
  grey[2] = 'a';

 /* binary search */
 left = 0;
 right = numTheRGBRecords - 1;
 do
 {
  middle = (left + right) / 2;
  cmp = strcasecmp(name, theRGBRecords[middle].name);
  if (cmp == 0)
  {
   rgbVal = theRGBRecords[middle].rgb;
   *r = GetRValue(rgbVal);
   *g = GetGValue(rgbVal);
   *b = GetBValue(rgbVal);
   free(name);
   return (1);
  } else
  if (cmp < 0)
  {
   right = middle - 1;
  } else
  {				/* > 0 */
   left = middle + 1;
  }
 } while (left <= right);

 /*
  * I don't like to run in a ColorInvalid error and to see no pixmap at all,
  * so simply return a red pixel. Should be wrapped in an #ifdef HeDu 
  */

 *r = 255;
 *g = 0;
 *b = 0;			/* red error pixel */

 free(name);
 return (1);
}

void
xpmFreeRgbNames(rgbn, rgbn_max)
xpmRgbName rgbn[];
int rgbn_max;

{
 /* nothing to do */
}

#endif				/* MSW part */
