diff src/objects-x.c @ 355:182f72e8cd0d r21-1-7

Import from CVS: tag r21-1-7
author cvs
date Mon, 13 Aug 2007 10:56:21 +0200
parents c5d627a313b1
children cc15677e0335
line wrap: on
line diff
--- a/src/objects-x.c	Mon Aug 13 10:55:35 2007 +0200
+++ b/src/objects-x.c	Mon Aug 13 10:56:21 2007 +0200
@@ -45,11 +45,13 @@
 
 /* Replacement for XAllocColor() that tries to return the nearest
    available color if the colormap is full.  Original was from FSFmacs,
-   but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25 */
+   but rewritten by Jareth Hein <jareth@camelot-soft.com> 97/11/25
+   Modified by Lee Kindness <lkindness@csl.co.uk> 31/08/99 to handle previous
+   total failure which was due to a read/write colorcell being the nearest
+   match - tries the next nearest...
 
-/* Return value is 1 for normal success, 2 for nearest color success,
-   3 for Non-deallocable sucess, and 0 for absolute failure (shouldn't
-   happen?) */
+   Return value is 1 for normal success, 2 for nearest color success,
+   3 for Non-deallocable sucess. */
 int
 allocate_nearest_color (Display *display, Colormap colormap, Visual *visual,
 		        XColor *color_def)
@@ -140,30 +142,35 @@
     }
   else
     {
+      XColor *cells = NULL;
+      /* JH: I can't believe there's no way to go backwards from a
+	 colormap ID and get its visual and number of entries, but X
+	 apparently isn't built that way... */
+      int no_cells = visual->map_entries;
+      status = 0;
+
       if (XAllocColor (display, colormap, color_def) != 0)
 	status = 1;
-      else
+      else while( status != 2 )
 	{
 	  /* If we got to this point, the colormap is full, so we're
 	     going to try and get the next closest color.  The algorithm used
 	     is a least-squares matching, which is what X uses for closest
 	     color matching with StaticColor visuals. */
-	  XColor *cells;
-	  /* JH: I can't believe there's no way to go backwards from a
-	     colormap ID and get its visual and number of entries, but X
-	     apparently isn't built that way... */
-	  int no_cells = visual->map_entries;
 	  int nearest;
 	  long nearest_delta, trial_delta;
 	  int x;
 
-	  cells = alloca_array (XColor, no_cells);
+	  if( cells == NULL )
+	      {
+		  cells = alloca_array (XColor, no_cells);
+		  for (x = 0; x < no_cells; x++)
+		      cells[x].pixel = x;
 
-	  for (x = 0; x < no_cells; x++)
-	    cells[x].pixel = x;
+		  /* read the current colormap */
+		  XQueryColors (display, colormap, cells, no_cells);
+	      }
 
-	  /* read the current colormap */
-	  XQueryColors (display, colormap, cells, no_cells);
 	  nearest = 0;
 	  /* I'm assuming CSE so I'm not going to condense this. */
 	  nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
@@ -184,7 +191,9 @@
 			     +
 			     (((color_def->blue >> 8) - (cells[x].blue >> 8))
 			      * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
-	      if (trial_delta < nearest_delta)
+
+	      /* less? Ignore cells marked as previously failing */
+	      if( (trial_delta < nearest_delta) && (cells[x].pixel != -1) )
 		{
 		  nearest = x;
 		  nearest_delta = trial_delta;
@@ -193,12 +202,15 @@
 	  color_def->red = cells[nearest].red;
 	  color_def->green = cells[nearest].green;
 	  color_def->blue = cells[nearest].blue;
-	  if (XAllocColor (display, colormap, color_def) != 0) {
-	    status = 2;
-	  } else {
-	    status = 0; /* JH: how does this happen??? DOES this happen??? */
-	    fprintf(stderr,"allocate_nearest_color returned 0!!!\n");
-	  }
+	  if (XAllocColor (display, colormap, color_def) != 0)
+	      status = 2;
+	  else
+	      /* LSK: Either the colour map has changed since
+	       * we read it, or the colour is allocated
+	       * read/write... Mark this cmap entry so it's
+	       * ignored in the next iteration.
+	       */
+	      cells[nearest].pixel = -1;
 	}
     }
   return status;