Blame gdk/win32/gdkcolor-win32.c

Packit 98cdb6
/* GDK - The GIMP Drawing Kit
Packit 98cdb6
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
Packit 98cdb6
 * Copyright (C) 1998-2002 Tor Lillqvist
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Lesser General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 98cdb6
 * Lesser General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Lesser General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
Packit 98cdb6
 * file for a list of people on the GTK+ Team.  See the ChangeLog
Packit 98cdb6
 * files for a list of changes.  These files are distributed with
Packit 98cdb6
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
#include <stdio.h>
Packit 98cdb6
#include <stdlib.h>
Packit 98cdb6
#include <string.h>
Packit 98cdb6
Packit 98cdb6
#include "gdkcolor.h"
Packit 98cdb6
#include "gdkscreen.h"
Packit 98cdb6
#include "gdkinternals.h"
Packit 98cdb6
#include "gdkprivate-win32.h"
Packit 98cdb6
Packit 98cdb6
static gint     gdk_colormap_match_color (GdkColormap      *cmap,
Packit 98cdb6
					  GdkColor         *color,
Packit 98cdb6
					  const gchar      *available);
Packit 98cdb6
static void     gdk_colormap_init        (GdkColormap      *colormap);
Packit 98cdb6
static void     gdk_colormap_class_init  (GdkColormapClass *klass);
Packit 98cdb6
static void     gdk_colormap_finalize    (GObject          *object);
Packit 98cdb6
Packit 98cdb6
static gpointer parent_class = NULL;
Packit 98cdb6
Packit 98cdb6
GType
Packit 98cdb6
gdk_colormap_get_type (void)
Packit 98cdb6
{
Packit 98cdb6
  static GType object_type = 0;
Packit 98cdb6
Packit 98cdb6
  if (!object_type)
Packit 98cdb6
    {
Packit 98cdb6
      const GTypeInfo object_info =
Packit 98cdb6
      {
Packit 98cdb6
        sizeof (GdkColormapClass),
Packit 98cdb6
        (GBaseInitFunc) NULL,
Packit 98cdb6
        (GBaseFinalizeFunc) NULL,
Packit 98cdb6
        (GClassInitFunc) gdk_colormap_class_init,
Packit 98cdb6
        NULL,           /* class_finalize */
Packit 98cdb6
        NULL,           /* class_data */
Packit 98cdb6
        sizeof (GdkColormap),
Packit 98cdb6
        0,              /* n_preallocs */
Packit 98cdb6
        (GInstanceInitFunc) gdk_colormap_init,
Packit 98cdb6
      };
Packit 98cdb6
      
Packit 98cdb6
      object_type = g_type_register_static (G_TYPE_OBJECT,
Packit 98cdb6
                                            "GdkColormap",
Packit 98cdb6
                                            &object_info, 0);
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  return object_type;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_colormap_init (GdkColormap *colormap)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
Packit 98cdb6
  private = g_new (GdkColormapPrivateWin32, 1);
Packit 98cdb6
Packit 98cdb6
  colormap->windowing_data = private;
Packit 98cdb6
  
Packit 98cdb6
  private->hpal = NULL;
Packit 98cdb6
  private->current_size = 0;
Packit 98cdb6
  private->use = NULL;
Packit 98cdb6
  private->hash = NULL;
Packit 98cdb6
  private->info = NULL;
Packit 98cdb6
Packit 98cdb6
  colormap->size = 0;
Packit 98cdb6
  colormap->colors = NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_colormap_class_init (GdkColormapClass *klass)
Packit 98cdb6
{
Packit 98cdb6
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
Packit 98cdb6
Packit 98cdb6
  parent_class = g_type_class_peek_parent (klass);
Packit 98cdb6
Packit 98cdb6
  object_class->finalize = gdk_colormap_finalize;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gdk_colormap_finalize (GObject *object)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormap *colormap = GDK_COLORMAP (object);
Packit 98cdb6
  GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  GDI_CALL (DeleteObject, (private->hpal));
Packit 98cdb6
Packit 98cdb6
  if (private->hash)
Packit 98cdb6
    g_hash_table_destroy (private->hash);
Packit 98cdb6
  
Packit 98cdb6
  g_free (private->info);
Packit 98cdb6
  g_free (colormap->colors);
Packit 98cdb6
  g_free (private);
Packit 98cdb6
  
Packit 98cdb6
  G_OBJECT_CLASS (parent_class)->finalize (object);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* Mimics XAllocColorCells. Allocate read/write color cells. */
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
alloc_color_cells (GdkColormap    *cmap,
Packit 98cdb6
		   gboolean        contig,
Packit 98cdb6
		   unsigned long   plane_masks_return[],
Packit 98cdb6
		   unsigned int    nplanes,
Packit 98cdb6
		   unsigned long   pixels_return[],
Packit 98cdb6
		   unsigned int	   npixels)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
Packit 98cdb6
  gint i, nfree, iret, start = 0;
Packit 98cdb6
Packit 98cdb6
  GDK_NOTE (COLORMAP, g_print ("alloc_color_cells: cmap=%p contig=%s npl=%d npix=%d",
Packit 98cdb6
			       cmapp, contig ? "TRUE" : "FALSE",
Packit 98cdb6
			       nplanes, npixels));
Packit 98cdb6
Packit 98cdb6
  switch (cmap->visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      nfree = 0;
Packit 98cdb6
      for (i = 0; i < cmap->size && nfree < npixels; i++)
Packit 98cdb6
	if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE &&
Packit 98cdb6
	    (!contig ||
Packit 98cdb6
	     (nfree == 0 || cmapp->use[i-1] == GDK_WIN32_PE_AVAILABLE)))
Packit 98cdb6
	  {
Packit 98cdb6
	    if (nfree == 0)
Packit 98cdb6
	      start = i;
Packit 98cdb6
	    nfree++;
Packit 98cdb6
	  }
Packit 98cdb6
	else if (contig)
Packit 98cdb6
	  nfree = 0;
Packit 98cdb6
Packit 98cdb6
      if (npixels > nfree)
Packit 98cdb6
	{
Packit 98cdb6
	  GDK_NOTE (COLORMAP, g_print ("... nope (%d > %d)\n",
Packit 98cdb6
				       npixels, nfree));
Packit 98cdb6
	  return FALSE;
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	GDK_NOTE (COLORMAP, g_print ("... ok\n"));
Packit 98cdb6
Packit 98cdb6
      iret = 0;
Packit 98cdb6
      for (i = start; i < cmap->size && iret < npixels; i++)
Packit 98cdb6
	if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
Packit 98cdb6
	  {
Packit 98cdb6
	    cmapp->use[i] = GDK_WIN32_PE_INUSE;
Packit 98cdb6
	    pixels_return[iret] = i;
Packit 98cdb6
	    iret++;
Packit 98cdb6
	  }
Packit 98cdb6
      g_assert (iret == npixels);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* The following functions are originally from Tk8.0, but heavily
Packit 98cdb6
   modified.  Here are tk's licensing terms. I hope these terms don't
Packit 98cdb6
   conflict with the GNU Lesser General Public License? They
Packit 98cdb6
   shouldn't, as they are looser that the GLPL, yes? */
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
This software is copyrighted by the Regents of the University of
Packit 98cdb6
California, Sun Microsystems, Inc., and other parties.  The following
Packit 98cdb6
terms apply to all files associated with the software unless explicitly
Packit 98cdb6
disclaimed in individual files.
Packit 98cdb6
Packit 98cdb6
The authors hereby grant permission to use, copy, modify, distribute,
Packit 98cdb6
and license this software and its documentation for any purpose, provided
Packit 98cdb6
that existing copyright notices are retained in all copies and that this
Packit 98cdb6
notice is included verbatim in any distributions. No written agreement,
Packit 98cdb6
license, or royalty fee is required for any of the authorized uses.
Packit 98cdb6
Modifications to this software may be copyrighted by their authors
Packit 98cdb6
and need not follow the licensing terms described here, provided that
Packit 98cdb6
the new terms are clearly indicated on the first page of each file where
Packit 98cdb6
they apply.
Packit 98cdb6
Packit 98cdb6
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
Packit 98cdb6
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
Packit 98cdb6
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
Packit 98cdb6
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
Packit 98cdb6
POSSIBILITY OF SUCH DAMAGE.
Packit 98cdb6
Packit 98cdb6
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
Packit 98cdb6
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
Packit 98cdb6
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
Packit 98cdb6
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
Packit 98cdb6
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
Packit 98cdb6
MODIFICATIONS.
Packit 98cdb6
Packit 98cdb6
GOVERNMENT USE: If you are acquiring this software on behalf of the
Packit 98cdb6
U.S. government, the Government shall have only "Restricted Rights"
Packit 98cdb6
in the software and related documentation as defined in the Federal 
Packit 98cdb6
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
Packit 98cdb6
are acquiring the software on behalf of the Department of Defense, the
Packit 98cdb6
software shall be classified as "Commercial Computer Software" and the
Packit 98cdb6
Government shall have only "Restricted Rights" as defined in Clause
Packit 98cdb6
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
Packit 98cdb6
authors grant the U.S. Government and others acting in its behalf
Packit 98cdb6
permission to use and distribute the software in accordance with the
Packit 98cdb6
terms specified in this license.
Packit 98cdb6
*/
Packit 98cdb6
Packit 98cdb6
/* Mimics XAllocColor. Allocate a read-only colormap entry. */
Packit 98cdb6
Packit 98cdb6
static int
Packit 98cdb6
alloc_color (GdkColormap  *cmap,
Packit 98cdb6
	     PALETTEENTRY *color,
Packit 98cdb6
	     guint        *pixelp)
Packit 98cdb6
{
Packit 98cdb6
  PALETTEENTRY entry, close_entry;
Packit 98cdb6
  COLORREF new_pixel;
Packit 98cdb6
  UINT index;
Packit 98cdb6
  GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
Packit 98cdb6
  gint i;
Packit 98cdb6
    
Packit 98cdb6
  entry = *color;
Packit 98cdb6
  entry.peFlags = 0;
Packit 98cdb6
Packit 98cdb6
  new_pixel = RGB (entry.peRed, entry.peGreen, entry.peBlue);
Packit 98cdb6
Packit 98cdb6
  switch (cmap->visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      /* Find the nearest existing palette entry. */
Packit 98cdb6
      index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
Packit 98cdb6
      GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
Packit 98cdb6
Packit 98cdb6
      GDK_NOTE (COLORMAP,
Packit 98cdb6
		g_print ("alloc_color: new_pixel=%06lx index=%d=%02x close=%06lx\n",
Packit 98cdb6
			 new_pixel, index, index,
Packit 98cdb6
			 RGB (close_entry.peRed, close_entry.peGreen, close_entry.peBlue)));
Packit 98cdb6
Packit 98cdb6
      if (new_pixel != RGB (close_entry.peRed, close_entry.peGreen,
Packit 98cdb6
			    close_entry.peBlue))
Packit 98cdb6
	{
Packit 98cdb6
	  /* Not a perfect match. */
Packit 98cdb6
	  if (cmapp->use[index] == GDK_WIN32_PE_AVAILABLE)
Packit 98cdb6
	    {
Packit 98cdb6
	      /* It was a nonused entry anyway, so we can use it, and
Packit 98cdb6
	       * set it to the correct color.
Packit 98cdb6
	       */
Packit 98cdb6
	      GDK_NOTE (COLORMAP, g_print ("... was free\n"));
Packit 98cdb6
	      GDI_CALL (SetPaletteEntries, (cmapp->hpal, index, 1, &entry));
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    {
Packit 98cdb6
	      /* The close entry found is in use, so search for a
Packit 98cdb6
	       * available slot.
Packit 98cdb6
	       */
Packit 98cdb6
	      gboolean done = FALSE;
Packit 98cdb6
	      for (i = 0; i < cmap->size; i++)
Packit 98cdb6
		if (cmapp->use[i] == GDK_WIN32_PE_AVAILABLE)
Packit 98cdb6
		  {
Packit 98cdb6
		    /* An available slot, use it. */
Packit 98cdb6
		    GDK_NOTE (COLORMAP,
Packit 98cdb6
			      g_print ("... use free slot %d%s\n",
Packit 98cdb6
				       i, (i >= cmapp->current_size) ?
Packit 98cdb6
				       ", will resize palette" : ""));
Packit 98cdb6
		    if (i >= cmapp->current_size)
Packit 98cdb6
		      {
Packit 98cdb6
			if (!ResizePalette (cmapp->hpal, i + 1))
Packit 98cdb6
			  {
Packit 98cdb6
			    WIN32_GDI_FAILED ("ResizePalette");
Packit 98cdb6
			    break;
Packit 98cdb6
			  }
Packit 98cdb6
			cmapp->current_size = i + 1;
Packit 98cdb6
		      }
Packit 98cdb6
		    if (!SetPaletteEntries (cmapp->hpal, i, 1, &entry))
Packit 98cdb6
		      {
Packit 98cdb6
			WIN32_GDI_FAILED ("SetPaletteEntries");
Packit 98cdb6
			i = cmap->size;
Packit 98cdb6
		      }
Packit 98cdb6
		    else
Packit 98cdb6
		      {
Packit 98cdb6
			done = TRUE;
Packit 98cdb6
			index = i;
Packit 98cdb6
		      }
Packit 98cdb6
		    break;
Packit 98cdb6
		  }
Packit 98cdb6
	      if (!done)
Packit 98cdb6
		{
Packit 98cdb6
		  /* No free slots available, or failed to resize
Packit 98cdb6
		   * palette or set palette entry.
Packit 98cdb6
		   */
Packit 98cdb6
		  GDK_NOTE (COLORMAP, g_print ("... failure\n"));
Packit 98cdb6
		  return FALSE;
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  /* We got a match, so use it. */
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      *pixelp = index;
Packit 98cdb6
      cmapp->use[index] = GDK_WIN32_PE_INUSE;
Packit 98cdb6
      GDK_NOTE (COLORMAP, g_print ("alloc_color: %p: "
Packit 98cdb6
				   "index=%3d=%02x for %02x %02x %02x: "
Packit 98cdb6
				   "%02x %02x %02x\n",
Packit 98cdb6
				   cmapp->hpal, index, index,
Packit 98cdb6
				   entry.peRed, entry.peGreen, entry.peBlue,
Packit 98cdb6
				   color->peRed, color->peGreen, color->peBlue));
Packit 98cdb6
      return TRUE;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_STATIC_COLOR:
Packit 98cdb6
      /* Find the nearest existing palette entry. */
Packit 98cdb6
      index = GetNearestPaletteIndex (cmapp->hpal, new_pixel);
Packit 98cdb6
      GetPaletteEntries (cmapp->hpal, index, 1, &close_entry);
Packit 98cdb6
      *color = close_entry;
Packit 98cdb6
      *pixelp = index;
Packit 98cdb6
      GDK_NOTE (COLORMAP, g_print ("alloc_color %p: "
Packit 98cdb6
				   "index=%3d=%02x for %02x %02x %02x: "
Packit 98cdb6
				   "%02x %02x %02x\n",
Packit 98cdb6
				   cmapp->hpal, index, index,
Packit 98cdb6
				   entry.peRed, entry.peGreen, entry.peBlue,
Packit 98cdb6
				   color->peRed, color->peGreen, color->peBlue));
Packit 98cdb6
      return TRUE;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_TRUE_COLOR:
Packit 98cdb6
      /* Determine what color will actually be used on non-colormap systems. */
Packit 98cdb6
Packit 98cdb6
      *pixelp = GetNearestColor (_gdk_display_hdc, new_pixel);
Packit 98cdb6
      color->peRed = GetRValue (*pixelp);
Packit 98cdb6
      color->peGreen = GetGValue (*pixelp);
Packit 98cdb6
      color->peBlue = GetBValue (*pixelp);
Packit 98cdb6
      return TRUE;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* Mimics XFreeColors. */
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
free_colors (GdkColormap *cmap,
Packit 98cdb6
	     gulong  	 *pixels,
Packit 98cdb6
	     gint    	  npixels,
Packit 98cdb6
	     gulong  	  planes)
Packit 98cdb6
{
Packit 98cdb6
  PALETTEENTRY pe;
Packit 98cdb6
  GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
Packit 98cdb6
  gint i;
Packit 98cdb6
#ifdef G_ENABLE_DEBUG
Packit 98cdb6
  gint set_black_count = 0;
Packit 98cdb6
#endif
Packit 98cdb6
  gboolean *cleared_entries;
Packit 98cdb6
Packit 98cdb6
  cleared_entries = g_new0 (gboolean, cmap->size);
Packit 98cdb6
Packit 98cdb6
  /* We don't have to do anything for non-palette devices. */
Packit 98cdb6
  
Packit 98cdb6
  switch (cmap->visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      for (i = 0; i < npixels; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  if (pixels[i] >= cmap->size)
Packit 98cdb6
	    ; /* Nothing */
Packit 98cdb6
	  else if (cmapp->use[pixels[i]] == GDK_WIN32_PE_STATIC)
Packit 98cdb6
	    ; /* Nothing either*/
Packit 98cdb6
	  else
Packit 98cdb6
	    {
Packit 98cdb6
	      cmapp->use[pixels[i]] = GDK_WIN32_PE_AVAILABLE;
Packit 98cdb6
	      cleared_entries[pixels[i]] = TRUE;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      for (i = cmapp->current_size - 1; i >= 0; i--)
Packit 98cdb6
	if (cmapp->use[i] != GDK_WIN32_PE_AVAILABLE)
Packit 98cdb6
	  break;
Packit 98cdb6
      if (i < cmapp->current_size - 1)
Packit 98cdb6
	{
Packit 98cdb6
	  GDK_NOTE (COLORMAP, g_print ("free_colors: hpal=%p resize=%d\n",
Packit 98cdb6
				       cmapp->hpal, i + 1));
Packit 98cdb6
	  if (!ResizePalette (cmapp->hpal, i + 1))
Packit 98cdb6
	    WIN32_GDI_FAILED ("ResizePalette");
Packit 98cdb6
	  else
Packit 98cdb6
	    cmapp->current_size = i + 1;
Packit 98cdb6
	}
Packit 98cdb6
      pe.peRed = pe.peGreen = pe.peBlue = pe.peFlags = 0;
Packit 98cdb6
      for (i = 0; i < cmapp->current_size; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  if (cleared_entries[i])
Packit 98cdb6
	    {
Packit 98cdb6
	      GDI_CALL (SetPaletteEntries, (cmapp->hpal, i, 1, &pe);;
Packit 98cdb6
	      GDK_NOTE (COLORMAP, set_black_count++);
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
#if 0
Packit 98cdb6
      GDK_NOTE (COLORMAP, _gdk_win32_print_hpalette (cmapp->hpal));
Packit 98cdb6
#else
Packit 98cdb6
      GDK_NOTE (COLORMAP, (set_black_count > 0 ?
Packit 98cdb6
			   g_print ("free_colors: %d (%d) set to black\n",
Packit 98cdb6
				    set_black_count, cmapp->current_size)
Packit 98cdb6
			   : (void) 0));
Packit 98cdb6
#endif
Packit 98cdb6
      g_free (cleared_entries);
Packit 98cdb6
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* Mimics XCreateColormap. */
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
create_colormap (GdkColormap *cmap,
Packit 98cdb6
		 gboolean     writeable)
Packit 98cdb6
{
Packit 98cdb6
  struct {
Packit 98cdb6
    LOGPALETTE pal;
Packit 98cdb6
    PALETTEENTRY pe[256-1];
Packit 98cdb6
  } lp;
Packit 98cdb6
  HPALETTE hpal;
Packit 98cdb6
  GdkColormapPrivateWin32 *cmapp = GDK_WIN32_COLORMAP_DATA (cmap);
Packit 98cdb6
  gint i;
Packit 98cdb6
Packit 98cdb6
  /* Allocate a starting palette with all the static colors. */
Packit 98cdb6
  hpal = GetStockObject (DEFAULT_PALETTE);
Packit 98cdb6
  lp.pal.palVersion = 0x300;
Packit 98cdb6
  lp.pal.palNumEntries = GetPaletteEntries (hpal, 0, 256, lp.pal.palPalEntry);
Packit 98cdb6
Packit 98cdb6
  if (cmap->visual->type == GDK_VISUAL_STATIC_COLOR &&
Packit 98cdb6
      cmap->visual->depth == 4)
Packit 98cdb6
    {
Packit 98cdb6
      /* Use only 16 colors */
Packit 98cdb6
      for (i = 8; i < 16; i++)
Packit 98cdb6
	lp.pal.palPalEntry[i] = lp.pal.palPalEntry[i+4];
Packit 98cdb6
      lp.pal.palNumEntries = 16;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < lp.pal.palNumEntries; i++)
Packit 98cdb6
    lp.pal.palPalEntry[i].peFlags = 0;
Packit 98cdb6
  GDK_NOTE (COLORMAP, (g_print ("Default palette %p: %d entries\n",
Packit 98cdb6
				hpal, lp.pal.palNumEntries),
Packit 98cdb6
		       _gdk_win32_print_paletteentries (lp.pal.palPalEntry,
Packit 98cdb6
						       lp.pal.palNumEntries)));
Packit 98cdb6
  DeleteObject (hpal);
Packit 98cdb6
  
Packit 98cdb6
  /* For writeable colormaps, allow all 256 entries to be set. They won't
Packit 98cdb6
   * set all 256 system palette entries anyhow, of course, but we shouldn't
Packit 98cdb6
   * let the app see that, I think.
Packit 98cdb6
   */
Packit 98cdb6
  if (writeable)
Packit 98cdb6
    cmapp->current_size = 0;
Packit 98cdb6
  else
Packit 98cdb6
    cmapp->current_size = lp.pal.palNumEntries;
Packit 98cdb6
Packit 98cdb6
  cmapp->private_val = writeable;
Packit 98cdb6
Packit 98cdb6
  if (!(cmapp->hpal = CreatePalette (&lp.pal)))
Packit 98cdb6
    WIN32_GDI_FAILED ("CreatePalette");
Packit 98cdb6
  else
Packit 98cdb6
    GDK_NOTE (COLORMAP, g_print ("Created palette %p\n", cmapp->hpal));
Packit 98cdb6
Packit 98cdb6
  switch (cmap->visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      cmapp->use = g_new (GdkWin32PalEntryState, cmap->size);
Packit 98cdb6
Packit 98cdb6
      /* Mark static colors in use. */
Packit 98cdb6
      for (i = 0; i < cmapp->current_size; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  cmapp->use[i] = GDK_WIN32_PE_STATIC;
Packit 98cdb6
	  cmapp->info[i].ref_count = G_MAXUINT/2;
Packit 98cdb6
	}
Packit 98cdb6
      /* Mark rest not in use */
Packit 98cdb6
      for (; i < cmap->size; i++)
Packit 98cdb6
	cmapp->use[i] = GDK_WIN32_PE_AVAILABLE;
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
sync_colors (GdkColormap *colormap)
Packit 98cdb6
{
Packit 98cdb6
  PALETTEENTRY *pe;
Packit 98cdb6
  GdkColormapPrivateWin32 *private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
  gint nlookup;
Packit 98cdb6
  gint i;
Packit 98cdb6
  
Packit 98cdb6
  pe = g_new (PALETTEENTRY, colormap->size);
Packit 98cdb6
  nlookup = GetPaletteEntries (private->hpal, 0, colormap->size, pe);
Packit 98cdb6
	  
Packit 98cdb6
  GDK_NOTE (COLORMAP, (g_print ("sync_colors: %p hpal=%p: %d entries\n",
Packit 98cdb6
				private, private->hpal, nlookup),
Packit 98cdb6
		       _gdk_win32_print_paletteentries (pe, nlookup)));
Packit 98cdb6
	  
Packit 98cdb6
  for (i = 0; i < nlookup; i++)
Packit 98cdb6
    {
Packit 98cdb6
      colormap->colors[i].pixel = i;
Packit 98cdb6
      colormap->colors[i].red = (pe[i].peRed * 65535) / 255;
Packit 98cdb6
      colormap->colors[i].green = (pe[i].peGreen * 65535) / 255;
Packit 98cdb6
      colormap->colors[i].blue = (pe[i].peBlue * 65535) / 255;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  for ( ; i < colormap->size; i++)
Packit 98cdb6
    {
Packit 98cdb6
      colormap->colors[i].pixel = i;
Packit 98cdb6
      colormap->colors[i].red = 0;
Packit 98cdb6
      colormap->colors[i].green = 0;
Packit 98cdb6
      colormap->colors[i].blue = 0;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  g_free (pe);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
GdkColormap*
Packit 98cdb6
gdk_colormap_new (GdkVisual *visual,
Packit 98cdb6
		  gboolean   private_cmap)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormap *colormap;
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (visual != NULL, NULL);
Packit 98cdb6
Packit 98cdb6
  colormap = g_object_new (gdk_colormap_get_type (), NULL);
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  colormap->visual = visual;
Packit 98cdb6
Packit 98cdb6
  colormap->size = visual->colormap_size;
Packit 98cdb6
Packit 98cdb6
  switch (visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      private->info = g_new0 (GdkColorInfo, colormap->size);
Packit 98cdb6
      colormap->colors = g_new (GdkColor, colormap->size);
Packit 98cdb6
      
Packit 98cdb6
      private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
Packit 98cdb6
					(GEqualFunc) gdk_color_equal);
Packit 98cdb6
      
Packit 98cdb6
      create_colormap (colormap, private_cmap);
Packit 98cdb6
Packit 98cdb6
      if (private_cmap)
Packit 98cdb6
	{
Packit 98cdb6
	  sync_colors (colormap);
Packit 98cdb6
#if 0 /* XXX is this needed or not? Seems redundant */
Packit 98cdb6
	  gdk_colormap_change (colormap, colormap->size);
Packit 98cdb6
#endif
Packit 98cdb6
	}
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_STATIC_GRAY:
Packit 98cdb6
    case GDK_VISUAL_STATIC_COLOR:
Packit 98cdb6
      create_colormap (colormap, FALSE);
Packit 98cdb6
      colormap->colors = g_new (GdkColor, colormap->size);
Packit 98cdb6
      sync_colors (colormap);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_TRUE_COLOR:
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return colormap;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
GdkColormap*
Packit 98cdb6
gdk_screen_get_system_colormap (GdkScreen *screen)
Packit 98cdb6
{
Packit 98cdb6
  static GdkColormap *colormap = NULL;
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (screen == _gdk_screen, NULL);
Packit 98cdb6
Packit 98cdb6
  if (!colormap)
Packit 98cdb6
    {
Packit 98cdb6
      colormap = g_object_new (gdk_colormap_get_type (), NULL);
Packit 98cdb6
      private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
      colormap->visual = gdk_visual_get_system ();
Packit 98cdb6
Packit 98cdb6
      colormap->size = colormap->visual->colormap_size;
Packit 98cdb6
Packit 98cdb6
      private->private_val = FALSE;
Packit 98cdb6
Packit 98cdb6
      switch (colormap->visual->type)
Packit 98cdb6
	{
Packit 98cdb6
	case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
	case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
	  private->info = g_new0 (GdkColorInfo, colormap->size);
Packit 98cdb6
	  private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash,
Packit 98cdb6
					    (GEqualFunc) gdk_color_equal);
Packit 98cdb6
	  /* Fallthrough */
Packit 98cdb6
Packit 98cdb6
	case GDK_VISUAL_STATIC_GRAY:
Packit 98cdb6
	case GDK_VISUAL_STATIC_COLOR:
Packit 98cdb6
	  create_colormap (colormap, FALSE);
Packit 98cdb6
Packit 98cdb6
	  colormap->colors = g_new (GdkColor, colormap->size);
Packit 98cdb6
	  sync_colors (colormap);
Packit 98cdb6
	  break;
Packit 98cdb6
Packit 98cdb6
	case GDK_VISUAL_TRUE_COLOR:
Packit 98cdb6
	  break;
Packit 98cdb6
Packit 98cdb6
	default:
Packit 98cdb6
	  g_assert_not_reached ();
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return colormap;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gint
Packit 98cdb6
gdk_colormap_get_system_size (void)
Packit 98cdb6
{
Packit 98cdb6
  return gdk_colormap_get_system ()->size;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gdk_colormap_change (GdkColormap *colormap,
Packit 98cdb6
		     gint         ncolors)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *cmapp;
Packit 98cdb6
  PALETTEENTRY *pe;
Packit 98cdb6
  int i;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GDK_IS_COLORMAP (colormap));
Packit 98cdb6
Packit 98cdb6
  cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  GDK_NOTE (COLORMAP, g_print ("gdk_colormap_change: hpal=%p ncolors=%d\n",
Packit 98cdb6
			       cmapp->hpal, ncolors));
Packit 98cdb6
Packit 98cdb6
  switch (colormap->visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      pe = g_new (PALETTEENTRY, ncolors);
Packit 98cdb6
Packit 98cdb6
      for (i = 0; i < ncolors; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  pe[i].peRed = (colormap->colors[i].red >> 8);
Packit 98cdb6
	  pe[i].peGreen = (colormap->colors[i].green >> 8);
Packit 98cdb6
	  pe[i].peBlue = (colormap->colors[i].blue >> 8);
Packit 98cdb6
	  pe[i].peFlags = 0;
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      GDI_CALL (SetPaletteEntries, (cmapp->hpal, 0, ncolors, pe));
Packit 98cdb6
      g_free (pe);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_colors_alloc (GdkColormap   *colormap,
Packit 98cdb6
		  gboolean       contiguous,
Packit 98cdb6
		  gulong        *planes,
Packit 98cdb6
		  gint           nplanes,
Packit 98cdb6
		  gulong        *pixels,
Packit 98cdb6
		  gint           npixels)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  gint return_val;
Packit 98cdb6
  gint i;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  return_val = alloc_color_cells (colormap, contiguous,
Packit 98cdb6
				  planes, nplanes, pixels, npixels);
Packit 98cdb6
Packit 98cdb6
  if (return_val)
Packit 98cdb6
    {
Packit 98cdb6
      for (i = 0; i < npixels; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  private->info[pixels[i]].ref_count++;
Packit 98cdb6
	  private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return return_val != 0;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gdk_colors_free (GdkColormap *colormap,
Packit 98cdb6
		 gulong      *in_pixels,
Packit 98cdb6
		 gint         in_npixels,
Packit 98cdb6
		 gulong       planes)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  gulong *pixels;
Packit 98cdb6
  gint npixels = 0;
Packit 98cdb6
  gint i;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GDK_IS_COLORMAP (colormap));
Packit 98cdb6
  g_return_if_fail (in_pixels != NULL);
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
Packit 98cdb6
      (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  pixels = g_new (gulong, in_npixels);
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < in_npixels; i++)
Packit 98cdb6
    {
Packit 98cdb6
      gulong pixel = in_pixels[i];
Packit 98cdb6
      
Packit 98cdb6
      if (private->use[pixel] == GDK_WIN32_PE_STATIC)
Packit 98cdb6
	continue;
Packit 98cdb6
Packit 98cdb6
      if (private->info[pixel].ref_count)
Packit 98cdb6
	{
Packit 98cdb6
	  private->info[pixel].ref_count--;
Packit 98cdb6
Packit 98cdb6
	  if (private->info[pixel].ref_count == 0)
Packit 98cdb6
	    {
Packit 98cdb6
	      pixels[npixels++] = pixel;
Packit 98cdb6
	      if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE))
Packit 98cdb6
		g_hash_table_remove (private->hash, &colormap->colors[pixel]);
Packit 98cdb6
	      private->info[pixel].flags = 0;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (npixels)
Packit 98cdb6
    free_colors (colormap, pixels, npixels, planes);
Packit 98cdb6
Packit 98cdb6
  g_free (pixels);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gdk_colormap_free_colors (GdkColormap    *colormap,
Packit 98cdb6
			  const GdkColor *colors,
Packit 98cdb6
			  gint            ncolors)
Packit 98cdb6
{
Packit 98cdb6
  gulong *pixels;
Packit 98cdb6
  gint i;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GDK_IS_COLORMAP (colormap));
Packit 98cdb6
  g_return_if_fail (colors != NULL);
Packit 98cdb6
Packit 98cdb6
  if ((colormap->visual->type != GDK_VISUAL_PSEUDO_COLOR) &&
Packit 98cdb6
      (colormap->visual->type != GDK_VISUAL_GRAYSCALE))
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  pixels = g_new (gulong, ncolors);
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < ncolors; i++)
Packit 98cdb6
    pixels[i] =  colors[i].pixel;
Packit 98cdb6
Packit 98cdb6
  gdk_colors_free (colormap, pixels, ncolors, 0);
Packit 98cdb6
Packit 98cdb6
  g_free (pixels);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/********************
Packit 98cdb6
 * Color allocation *
Packit 98cdb6
 ********************/
Packit 98cdb6
Packit 98cdb6
/* Try to allocate a single color using alloc_color. If it succeeds,
Packit 98cdb6
 * cache the result in our colormap, and store in ret.
Packit 98cdb6
 */
Packit 98cdb6
static gboolean 
Packit 98cdb6
gdk_colormap_alloc1 (GdkColormap *colormap,
Packit 98cdb6
		     GdkColor    *color,
Packit 98cdb6
		     GdkColor    *ret)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  PALETTEENTRY pe;
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  pe.peRed = color->red >> 8;
Packit 98cdb6
  pe.peGreen = color->green >> 8;
Packit 98cdb6
  pe.peBlue = color->blue >> 8;
Packit 98cdb6
Packit 98cdb6
  if (alloc_color (colormap, &pe, &ret->pixel))
Packit 98cdb6
    {
Packit 98cdb6
      ret->red = (pe.peRed * 65535) / 255;
Packit 98cdb6
      ret->green = (pe.peGreen * 65535) / 255;
Packit 98cdb6
      ret->blue = (pe.peBlue * 65535) / 255;
Packit 98cdb6
      
Packit 98cdb6
      if ((guint) ret->pixel < colormap->size)
Packit 98cdb6
	{
Packit 98cdb6
	  if (private->info[ret->pixel].ref_count) /* got a duplicate */
Packit 98cdb6
	    {
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    {
Packit 98cdb6
	      colormap->colors[ret->pixel] = *color;
Packit 98cdb6
	      colormap->colors[ret->pixel].pixel = ret->pixel;
Packit 98cdb6
	      private->info[ret->pixel].ref_count = 1;
Packit 98cdb6
Packit 98cdb6
	      g_hash_table_insert (private->hash,
Packit 98cdb6
				   &colormap->colors[ret->pixel],
Packit 98cdb6
				   &colormap->colors[ret->pixel]);
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gdk_colormap_alloc_colors_writeable (GdkColormap *colormap,
Packit 98cdb6
				     GdkColor    *colors,
Packit 98cdb6
				     gint         ncolors,
Packit 98cdb6
				     gboolean     writeable,
Packit 98cdb6
				     gboolean     best_match,
Packit 98cdb6
				     gboolean    *success)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  gulong *pixels;
Packit 98cdb6
  gboolean status;
Packit 98cdb6
  gint i, index;
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  if (private->private_val)
Packit 98cdb6
    {
Packit 98cdb6
      index = 0;
Packit 98cdb6
      for (i=0; i
Packit 98cdb6
	{
Packit 98cdb6
	  while ((index < colormap->size) &&
Packit 98cdb6
		 (private->info[index].ref_count != 0))
Packit 98cdb6
	    index++;
Packit 98cdb6
	  
Packit 98cdb6
	  if (index < colormap->size)
Packit 98cdb6
	    {
Packit 98cdb6
	      colors[i].pixel = index;
Packit 98cdb6
	      success[i] = TRUE;
Packit 98cdb6
	      private->info[index].ref_count++;
Packit 98cdb6
	      private->info[i].flags |= GDK_COLOR_WRITEABLE;
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    break;
Packit 98cdb6
	}
Packit 98cdb6
      return i;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      pixels = g_new (gulong, ncolors);
Packit 98cdb6
Packit 98cdb6
      /* Allocation of a writeable color cells */
Packit 98cdb6
      status =  alloc_color_cells (colormap, FALSE, NULL, 0, pixels, ncolors);
Packit 98cdb6
      if (status)
Packit 98cdb6
	{
Packit 98cdb6
	  for (i = 0; i < ncolors; i++)
Packit 98cdb6
	    {
Packit 98cdb6
	      colors[i].pixel = pixels[i];
Packit 98cdb6
	      private->info[pixels[i]].ref_count++;
Packit 98cdb6
	      private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      
Packit 98cdb6
      g_free (pixels);
Packit 98cdb6
Packit 98cdb6
      return status ? ncolors : 0; 
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gdk_colormap_alloc_colors_private (GdkColormap *colormap,
Packit 98cdb6
				   GdkColor    *colors,
Packit 98cdb6
				   gint         ncolors,
Packit 98cdb6
				   gboolean     writeable,
Packit 98cdb6
				   gboolean     best_match,
Packit 98cdb6
				   gboolean    *success)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *cmapp;
Packit 98cdb6
  gint i, index;
Packit 98cdb6
  PALETTEENTRY pe;
Packit 98cdb6
  gint nremaining = 0;
Packit 98cdb6
  
Packit 98cdb6
  cmapp = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
  index = -1;
Packit 98cdb6
Packit 98cdb6
  /* First, store the colors we have room for */
Packit 98cdb6
Packit 98cdb6
  index = 0;
Packit 98cdb6
  for (i = 0; i < ncolors; i++)
Packit 98cdb6
    {
Packit 98cdb6
      if (!success[i])
Packit 98cdb6
	{
Packit 98cdb6
	  while ((index < colormap->size) &&
Packit 98cdb6
		 (cmapp->info[index].ref_count != 0))
Packit 98cdb6
	    index++;
Packit 98cdb6
Packit 98cdb6
	  if (index < colormap->size)
Packit 98cdb6
	    {
Packit 98cdb6
	      if (index >= cmapp->current_size)
Packit 98cdb6
		{
Packit 98cdb6
		  if (!ResizePalette (cmapp->hpal, index + 1))
Packit 98cdb6
		    {
Packit 98cdb6
		      WIN32_GDI_FAILED ("ResizePalette");
Packit 98cdb6
		      nremaining++;
Packit 98cdb6
		    }
Packit 98cdb6
		  else
Packit 98cdb6
		    cmapp->current_size = index + 1;
Packit 98cdb6
		}
Packit 98cdb6
	      if (index < cmapp->current_size)
Packit 98cdb6
		{
Packit 98cdb6
		  pe.peRed = colors[i].red >> 8;
Packit 98cdb6
		  pe.peBlue = colors[i].blue >> 8;
Packit 98cdb6
		  pe.peGreen = colors[i].green >> 8;
Packit 98cdb6
		  pe.peFlags = 0;
Packit 98cdb6
		  
Packit 98cdb6
		  if (!SetPaletteEntries (cmapp->hpal, index, 1, &pe))
Packit 98cdb6
		    {
Packit 98cdb6
		      WIN32_GDI_FAILED ("SetPaletteEntries");
Packit 98cdb6
		      nremaining++;
Packit 98cdb6
		    }
Packit 98cdb6
		  else
Packit 98cdb6
		    {
Packit 98cdb6
		      success[i] = TRUE;
Packit 98cdb6
Packit 98cdb6
		      colors[i].pixel = index;
Packit 98cdb6
		      colormap->colors[index] = colors[i];
Packit 98cdb6
		      cmapp->info[index].ref_count++;
Packit 98cdb6
		    }
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    nremaining++;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  if (nremaining > 0 && best_match)
Packit 98cdb6
    {
Packit 98cdb6
      /* Get best matches for remaining colors */
Packit 98cdb6
Packit 98cdb6
      gchar *available = g_new (gchar, colormap->size);
Packit 98cdb6
      for (i = 0; i < colormap->size; i++)
Packit 98cdb6
	available[i] = TRUE;
Packit 98cdb6
Packit 98cdb6
      for (i=0; i
Packit 98cdb6
	{
Packit 98cdb6
	  if (!success[i])
Packit 98cdb6
	    {
Packit 98cdb6
	      index = gdk_colormap_match_color (colormap, 
Packit 98cdb6
						&colors[i], 
Packit 98cdb6
						available);
Packit 98cdb6
	      if (index != -1)
Packit 98cdb6
		{
Packit 98cdb6
		  colors[i] = colormap->colors[index];
Packit 98cdb6
		  cmapp->info[index].ref_count++;
Packit 98cdb6
Packit 98cdb6
		  success[i] = TRUE;
Packit 98cdb6
		  nremaining--;
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      g_free (available);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return (ncolors - nremaining);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gdk_colormap_alloc_colors_shared (GdkColormap *colormap,
Packit 98cdb6
				  GdkColor    *colors,
Packit 98cdb6
				  gint         ncolors,
Packit 98cdb6
				  gboolean     writeable,
Packit 98cdb6
				  gboolean     best_match,
Packit 98cdb6
				  gboolean    *success)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  gint i, index;
Packit 98cdb6
  gint nremaining = 0;
Packit 98cdb6
  gint nfailed = 0;
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
  index = -1;
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < ncolors; i++)
Packit 98cdb6
    {
Packit 98cdb6
      if (!success[i])
Packit 98cdb6
	{
Packit 98cdb6
	  if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i]))
Packit 98cdb6
	    success[i] = TRUE;
Packit 98cdb6
	  else
Packit 98cdb6
	    nremaining++;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  if (nremaining > 0 && best_match)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *available = g_new (gchar, colormap->size);
Packit 98cdb6
      for (i = 0; i < colormap->size; i++)
Packit 98cdb6
	available[i] = ((private->info[i].ref_count == 0) ||
Packit 98cdb6
			!(private->info[i].flags & GDK_COLOR_WRITEABLE));
Packit 98cdb6
      while (nremaining > 0)
Packit 98cdb6
	{
Packit 98cdb6
	  for (i = 0; i < ncolors; i++)
Packit 98cdb6
	    {
Packit 98cdb6
	      if (!success[i])
Packit 98cdb6
		{
Packit 98cdb6
		  index = gdk_colormap_match_color (colormap, &colors[i], available);
Packit 98cdb6
		  if (index != -1)
Packit 98cdb6
		    {
Packit 98cdb6
		      if (private->info[index].ref_count)
Packit 98cdb6
			{
Packit 98cdb6
			  private->info[index].ref_count++;
Packit 98cdb6
			  colors[i] = colormap->colors[index];
Packit 98cdb6
			  success[i] = TRUE;
Packit 98cdb6
			  nremaining--;
Packit 98cdb6
			}
Packit 98cdb6
		      else
Packit 98cdb6
			{
Packit 98cdb6
			  if (gdk_colormap_alloc1 (colormap, 
Packit 98cdb6
						   &colormap->colors[index],
Packit 98cdb6
						   &colors[i]))
Packit 98cdb6
			    {
Packit 98cdb6
			      success[i] = TRUE;
Packit 98cdb6
			      nremaining--;
Packit 98cdb6
			      break;
Packit 98cdb6
			    }
Packit 98cdb6
			  else
Packit 98cdb6
			    {
Packit 98cdb6
			      available[index] = FALSE;
Packit 98cdb6
			    }
Packit 98cdb6
			}
Packit 98cdb6
		    }
Packit 98cdb6
		  else
Packit 98cdb6
		    {
Packit 98cdb6
		      nfailed++;
Packit 98cdb6
		      nremaining--;
Packit 98cdb6
		      success[i] = 2; /* flag as permanent failure */
Packit 98cdb6
		    }
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      g_free (available);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* Change back the values we flagged as permanent failures */
Packit 98cdb6
  if (nfailed > 0)
Packit 98cdb6
    {
Packit 98cdb6
      for (i = 0; i < ncolors; i++)
Packit 98cdb6
	if (success[i] == 2)
Packit 98cdb6
	  success[i] = FALSE;
Packit 98cdb6
      nremaining = nfailed;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  return (ncolors - nremaining);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap,
Packit 98cdb6
				       GdkColor    *colors,
Packit 98cdb6
				       gint         ncolors,
Packit 98cdb6
				       gboolean     writeable,
Packit 98cdb6
				       gboolean     best_match,
Packit 98cdb6
				       gboolean    *success)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  GdkColor *lookup_color;
Packit 98cdb6
  gint i;
Packit 98cdb6
  gint nremaining = 0;
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  /* Check for an exact match among previously allocated colors */
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < ncolors; i++)
Packit 98cdb6
    {
Packit 98cdb6
      if (!success[i])
Packit 98cdb6
	{
Packit 98cdb6
	  lookup_color = g_hash_table_lookup (private->hash, &colors[i]);
Packit 98cdb6
	  if (lookup_color)
Packit 98cdb6
	    {
Packit 98cdb6
	      private->info[lookup_color->pixel].ref_count++;
Packit 98cdb6
	      colors[i].pixel = lookup_color->pixel;
Packit 98cdb6
	      success[i] = TRUE;
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    nremaining++;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* If that failed, we try to allocate a new color, or approxmiate
Packit 98cdb6
   * with what we can get if best_match is TRUE.
Packit 98cdb6
   */
Packit 98cdb6
  if (nremaining > 0)
Packit 98cdb6
    {
Packit 98cdb6
      if (private->private_val)
Packit 98cdb6
	return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success);
Packit 98cdb6
      else
Packit 98cdb6
	return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return 0;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gint
Packit 98cdb6
gdk_colormap_alloc_colors (GdkColormap *colormap,
Packit 98cdb6
			   GdkColor    *colors,
Packit 98cdb6
			   gint         ncolors,
Packit 98cdb6
			   gboolean     writeable,
Packit 98cdb6
			   gboolean     best_match,
Packit 98cdb6
			   gboolean    *success)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  GdkVisual *visual;
Packit 98cdb6
  gint i;
Packit 98cdb6
  gint nremaining = 0;
Packit 98cdb6
  PALETTEENTRY pe;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
Packit 98cdb6
  g_return_val_if_fail (colors != NULL, FALSE);
Packit 98cdb6
  g_return_val_if_fail (success != NULL, ncolors);
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < ncolors; i++)
Packit 98cdb6
    success[i] = FALSE;
Packit 98cdb6
Packit 98cdb6
  switch (colormap->visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
    case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
      if (writeable)
Packit 98cdb6
	return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors,
Packit 98cdb6
						    writeable, best_match, success);
Packit 98cdb6
      else
Packit 98cdb6
	return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors,
Packit 98cdb6
						    writeable, best_match, success);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_TRUE_COLOR:
Packit 98cdb6
      visual = colormap->visual;
Packit 98cdb6
Packit 98cdb6
      for (i = 0; i < ncolors; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  colors[i].pixel =
Packit 98cdb6
	    (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) +
Packit 98cdb6
	     ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) +
Packit 98cdb6
	     ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift));
Packit 98cdb6
	  success[i] = TRUE;
Packit 98cdb6
	}
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_STATIC_GRAY:
Packit 98cdb6
    case GDK_VISUAL_STATIC_COLOR:
Packit 98cdb6
      for (i = 0; i < ncolors; i++)
Packit 98cdb6
	{
Packit 98cdb6
	  pe.peRed = colors[i].red >> 8;
Packit 98cdb6
	  pe.peGreen = colors[i].green >> 8;
Packit 98cdb6
	  pe.peBlue = colors[i].blue >> 8;
Packit 98cdb6
	  if (alloc_color (colormap, &pe, &colors[i].pixel))
Packit 98cdb6
	    success[i] = TRUE;
Packit 98cdb6
	  else
Packit 98cdb6
	    nremaining++;
Packit 98cdb6
	}
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_DIRECT_COLOR:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return nremaining;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
gdk_colormap_query_color (GdkColormap *colormap,
Packit 98cdb6
			  gulong       pixel,
Packit 98cdb6
			  GdkColor    *result)
Packit 98cdb6
{
Packit 98cdb6
  GdkVisual *visual;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GDK_IS_COLORMAP (colormap));
Packit 98cdb6
  
Packit 98cdb6
  visual = gdk_colormap_get_visual (colormap);
Packit 98cdb6
Packit 98cdb6
  switch (visual->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_VISUAL_DIRECT_COLOR:
Packit 98cdb6
    case GDK_VISUAL_TRUE_COLOR:
Packit 98cdb6
      result->red = 65535. * (double)((pixel & visual->red_mask) >> visual->red_shift) / ((1 << visual->red_prec) - 1);
Packit 98cdb6
      result->green = 65535. * (double)((pixel & visual->green_mask) >> visual->green_shift) / ((1 << visual->green_prec) - 1);
Packit 98cdb6
      result->blue = 65535. * (double)((pixel & visual->blue_mask) >> visual->blue_shift) / ((1 << visual->blue_prec) - 1);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_STATIC_GRAY:
Packit 98cdb6
    case GDK_VISUAL_GRAYSCALE:
Packit 98cdb6
      result->red = result->green = result->blue = 65535. * (double)pixel/((1<<visual->depth) - 1);
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_VISUAL_STATIC_COLOR:
Packit 98cdb6
    case GDK_VISUAL_PSEUDO_COLOR:
Packit 98cdb6
      result->red = colormap->colors[pixel].red;
Packit 98cdb6
      result->green = colormap->colors[pixel].green;
Packit 98cdb6
      result->blue = colormap->colors[pixel].blue;
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      g_assert_not_reached ();
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
gdk_color_change (GdkColormap *colormap,
Packit 98cdb6
		  GdkColor    *color)
Packit 98cdb6
{
Packit 98cdb6
  GdkColormapPrivateWin32 *private;
Packit 98cdb6
  PALETTEENTRY pe;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_COLORMAP (colormap), FALSE);
Packit 98cdb6
  g_return_val_if_fail (color != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  private = GDK_WIN32_COLORMAP_DATA (colormap);
Packit 98cdb6
Packit 98cdb6
  if (color->pixel < 0 || color->pixel >= colormap->size)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  if (private->use[color->pixel] == GDK_WIN32_PE_STATIC)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  pe.peRed = color->red >> 8;
Packit 98cdb6
  pe.peGreen = color->green >> 8;
Packit 98cdb6
  pe.peBlue = color->blue >> 8;
Packit 98cdb6
Packit 98cdb6
  GDI_CALL (SetPaletteEntries, (private->hpal, color->pixel, 1, &pe);;
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gdk_colormap_match_color (GdkColormap *cmap,
Packit 98cdb6
			  GdkColor    *color,
Packit 98cdb6
			  const gchar *available)
Packit 98cdb6
{
Packit 98cdb6
  GdkColor *colors;
Packit 98cdb6
  guint sum, min;
Packit 98cdb6
  gint rdiff, gdiff, bdiff;
Packit 98cdb6
  gint i, index;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (cmap != NULL, 0);
Packit 98cdb6
  g_return_val_if_fail (color != NULL, 0);
Packit 98cdb6
Packit 98cdb6
  colors = cmap->colors;
Packit 98cdb6
  min = 3 * (65536);
Packit 98cdb6
  index = -1;
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < cmap->size; i++)
Packit 98cdb6
    {
Packit 98cdb6
      if ((!available) || (available && available[i]))
Packit 98cdb6
	{
Packit 98cdb6
	  rdiff = (color->red - colors[i].red);
Packit 98cdb6
	  gdiff = (color->green - colors[i].green);
Packit 98cdb6
	  bdiff = (color->blue - colors[i].blue);
Packit 98cdb6
Packit 98cdb6
	  sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
Packit 98cdb6
Packit 98cdb6
	  if (sum < min)
Packit 98cdb6
	    {
Packit 98cdb6
	      index = i;
Packit 98cdb6
	      min = sum;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return index;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
GdkScreen*
Packit 98cdb6
gdk_colormap_get_screen (GdkColormap *cmap)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GDK_IS_COLORMAP (cmap), NULL);
Packit 98cdb6
Packit 98cdb6
  return _gdk_screen;
Packit 98cdb6
}
Packit 98cdb6