]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorsel.c
26d34078e8196f638af69d6b164198aa6a749dbc
[~andy/gtk] / gtk / gtkcolorsel.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "gdkconfig.h"
29
30 #if defined (GDK_WINDOWING_X11)
31 #include "x11/gdkx.h"
32 #endif
33 #include "gdk/gdkkeysyms.h"
34 #include "gtkcolorsel.h"
35 #include "gtkhsv.h"
36 #include "gtkwindow.h"
37 #include "gtkselection.h"
38 #include "gtkdnd.h"
39 #include "gtkdrawingarea.h"
40 #include "gtksignal.h"
41 #include "gtkhbox.h"
42 #include "gtkhbbox.h"
43 #include "gtkrc.h"
44 #include "gtkframe.h"
45 #include "gtktable.h"
46 #include "gtklabel.h"
47 #include "gtkpixmap.h"
48 #include "gtkspinbutton.h"
49 #include "gtkrange.h"
50 #include "gtkhscale.h"
51 #include "gtkentry.h"
52 #include "gtkbutton.h"
53 #include "gtkhseparator.h"
54 #include "gtkintl.h"
55
56 enum {
57   COLOR_CHANGED,
58   LAST_SIGNAL
59 };
60
61
62
63 enum {
64   COLORSEL_RED = 0,
65   COLORSEL_GREEN = 1,
66   COLORSEL_BLUE = 2,
67   COLORSEL_OPACITY = 3,
68   COLORSEL_HUE,
69   COLORSEL_SATURATION,
70   COLORSEL_VALUE,
71   COLORSEL_NUM_CHANNELS
72 };
73
74 typedef struct _ColorSelectionPrivate ColorSelectionPrivate;
75
76 struct _ColorSelectionPrivate
77 {
78   guint use_opacity : 1;
79   guint use_palette : 1;
80   guint changing : 1;
81   guint default_set : 1;
82   
83   /* The color dropper */
84   guint moving_dropper : 1;
85   
86   gdouble color[COLORSEL_NUM_CHANNELS];
87   gdouble old_color[COLORSEL_NUM_CHANNELS];
88   
89   GtkWidget *triangle_colorsel;
90   GtkWidget *hue_spinbutton;
91   GtkWidget *sat_spinbutton;
92   GtkWidget *val_spinbutton;
93   GtkWidget *red_spinbutton;
94   GtkWidget *green_spinbutton;
95   GtkWidget *blue_spinbutton;
96   GtkWidget *opacity_slider;
97   GtkWidget *opacity_label;
98   GtkWidget *opacity_entry;
99   GtkWidget *palette_frame;
100   GtkWidget *hex_entry;
101   
102   /* The Palette code */
103   GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
104   GtkWidget *last_palette;
105   
106   /* The color_sample stuff */
107   GtkWidget *sample_area;
108   GtkWidget *old_sample;
109   GtkWidget *cur_sample;
110   GtkWidget *colorsel;
111 };
112
113
114 static void gtk_color_selection_init            (GtkColorSelection       *colorsel);
115 static void gtk_color_selection_class_init      (GtkColorSelectionClass  *klass);
116 static void gtk_color_selection_destroy         (GtkObject               *object);
117 static void update_color                        (GtkColorSelection       *colorsel);
118
119 static gpointer parent_class = NULL;
120 static guint color_selection_signals[LAST_SIGNAL] = { 0 };
121
122
123 /* The cursor for the dropper */
124 #define DROPPER_WIDTH 17
125 #define DROPPER_HEIGHT 17
126 #define DROPPER_X_HOT 2
127 #define DROPPER_Y_HOT 16
128
129
130 static char dropper_bits[] = {
131   0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00,
132   0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01,
133   0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01,
134   0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01,
135   0xff, 0xff, 0x01, };
136
137 static char dropper_mask[] = {
138   0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01,
139   0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00,
140   0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00,
141   0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00,
142   0x02, 0x00, 0x00, };
143
144 static GdkCursor *picker_cursor = NULL;
145
146
147 /* XPM */
148 static char *picker[] = {
149   /* columns rows colors chars-per-pixel */
150   "25 25 8 1",
151   "  c Gray0",
152   ". c #020202",
153   "X c Gray12",
154   "o c Gray13",
155   "O c Gray52",
156   "+ c #929292",
157   "@ c Gray100",
158   "# c None",
159   /* pixels */
160   "#########################",
161   "#########################",
162   "#########################",
163   "#########################",
164   "#########################",
165   "#################   #####",
166   "################     ####",
167   "################     +###",
168   "#############        +###",
169   "##############      ++###",
170   "#############+@   +++####",
171   "############+@@@  +######",
172   "###########+@@@ + +######",
173   "##########+@@@ ++#+######",
174   "#########+@@@ ++#########",
175   "########+@@@ ++##########",
176   "#######+@@@ ++###########",
177   "######+@@@ ++############",
178   "######+@@ ++#############",
179   "#####+@  ++##############",
180   "###### +++###############",
181   "#########################",
182   "#########################",
183   "#########################",
184   "#########################"
185 };
186
187
188 /*
189  *
190  * The Sample Color
191  *
192  */
193 #define SAMPLE_WIDTH  64
194 #define SAMPLE_HEIGHT 28
195
196 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which);
197 static void color_sample_draw_samples (GtkColorSelection *colorsel);
198
199 static void
200 color_sample_drag_begin (GtkWidget      *widget,
201                          GdkDragContext *context,
202                          gpointer        data)
203 {
204   GtkColorSelection *colorsel = data;
205   ColorSelectionPrivate *priv;
206   GtkWidget *window;
207   gdouble colors[4];
208   gdouble *colsrc;
209   GdkColor bg;
210   gint n, i;
211   
212   priv = colorsel->private_data;
213   window = gtk_window_new (GTK_WINDOW_POPUP);
214   gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
215   gtk_widget_set_usize (window, 48, 32);
216   gtk_widget_realize (window);
217   gtk_object_set_data_full (GTK_OBJECT (widget),
218                             "gtk-color-selection-drag-window",
219                             window,
220                             (GtkDestroyNotify) gtk_widget_destroy);
221   
222   if (widget == priv->old_sample)
223     colsrc = priv->old_color;
224   else
225     colsrc = priv->color;
226   
227   for (i=0, n = COLORSEL_RED; n <= COLORSEL_BLUE; n++)
228     {
229       colors[i++] = colsrc[n];
230     }
231   
232   if (priv->use_opacity)
233     {
234       colors[i] = colsrc[COLORSEL_OPACITY];
235     }
236   
237   bg.red = 0xffff * colors[0];
238   bg.green = 0xffff * colors[1];
239   bg.blue = 0xffff * colors[2];
240   
241   gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
242   gdk_window_set_background (window->window, &bg);
243   
244   gtk_drag_set_icon_widget (context, window, -2, -2);
245 }
246
247 static void
248 color_sample_drag_end (GtkWidget      *widget,
249                        GdkDragContext *context,
250                        gpointer        data)
251 {
252   gtk_object_set_data (GTK_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
253 }
254
255 static void
256 color_sample_drop_handle (GtkWidget        *widget,
257                           GdkDragContext   *context,
258                           gint              x,
259                           gint              y,
260                           GtkSelectionData *selection_data,
261                           guint             info,
262                           guint             time,
263                           gpointer          data)
264 {
265   GtkColorSelection *colorsel = data;
266   ColorSelectionPrivate *priv;
267   guint16 *vals;
268   gdouble color[4];
269   priv = colorsel->private_data;
270   
271   /* This is currently a guint16 array of the format:
272    * R
273    * G
274    * B
275    * opacity
276    */
277   
278   if (selection_data->length < 0)
279     return;
280   
281   if ((selection_data->format != 16) ||
282       (selection_data->length != 8))
283     {
284       g_warning ("Received invalid color data\n");
285       return;
286     }
287   
288   vals = (guint16 *)selection_data->data;
289   
290   if (widget == priv->cur_sample)
291     {
292       color[0] = (gdouble)vals[0] / 0xffff;
293       color[1] = (gdouble)vals[1] / 0xffff;
294       color[2] = (gdouble)vals[2] / 0xffff;
295       color[3] = (gdouble)vals[3] / 0xffff;
296       
297       gtk_color_selection_set_color (colorsel, color);
298     }
299 }
300
301 static void
302 color_sample_drag_handle (GtkWidget        *widget,
303                           GdkDragContext   *context,
304                           GtkSelectionData *selection_data,
305                           guint             info,
306                           guint             time,
307                           gpointer          data)
308 {
309   GtkColorSelection *colorsel = data;
310   ColorSelectionPrivate *priv;
311   guint16 vals[4];
312   gdouble *colsrc;
313   
314   priv = colorsel->private_data;
315   
316   if (widget == priv->old_sample)
317     colsrc = priv->old_color;
318   else
319     colsrc = priv->color;
320   
321   vals[0] = colsrc[COLORSEL_RED] * 0xffff;
322   vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
323   vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
324   vals[3] = priv->use_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
325   
326   gtk_selection_data_set (selection_data,
327                           gdk_atom_intern ("application/x-color", FALSE),
328                           16, (guchar *)vals, 8);
329 }
330
331 /* which = 0 means draw old sample, which = 1 means draw new */
332 static void
333 color_sample_draw_sample (GtkColorSelection *colorsel, int which)
334 {
335   GtkWidget *da;
336   gint x, y, i, wid, heig, f, n, goff;
337   guchar c[3 * 2], cc[3 * 4], *cp = c;
338   gdouble o;
339   guchar *buf;
340   ColorSelectionPrivate *priv;
341   
342   g_return_if_fail (colorsel != NULL);
343   priv = colorsel->private_data;
344   
345   g_return_if_fail (priv->sample_area != NULL);
346   if (!GTK_WIDGET_DRAWABLE (priv->sample_area))
347     return;
348   
349   if (which == 0)
350     {
351       da = priv->old_sample;
352       for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
353         c[n] = (guchar) (255.0 * priv->old_color[i]);
354       goff = 0;
355     }
356   else
357     {
358       da = priv->cur_sample;
359       for (n = 0, i = COLORSEL_RED; n < 3; n++, i++)
360         c[n] = (guchar) (255.0 * priv->color[i]);
361       goff =  priv->old_sample->allocation.width % 32;
362     }
363   
364   wid = da->allocation.width;
365   heig = da->allocation.height;
366   
367   buf = g_new(guchar, 3 * wid * heig);
368   
369 #if 0
370   i = COLORSEL_RED;
371   for (n = 0; n < 3; n++)
372     {
373       c[n] = (guchar) (255.0 * priv->old_color[i]);
374       c[n + 3] = (guchar) (255.0 * priv->color[i++]);
375     }
376 #endif
377   
378   if (priv->use_opacity)
379     {
380       o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY];
381       
382       for (n = 0; n < 3; n++)
383         {
384           cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n]));
385           cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n]));
386         }
387       cp = cc;
388     }
389   
390   i = 0;
391   for (y = 0; y < heig; y++)
392     {
393       for (x = 0; x < wid; x++)
394         {
395           if (priv->use_opacity)
396             f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16));
397           else
398             f = 0;
399           
400           for (n = 0; n < 3; n++)
401             buf[i++] = cp[n + f];
402         }
403     }
404   
405   gdk_draw_rgb_image(da->window,
406                      da->style->black_gc,
407                      0, 0,
408                      wid, heig,
409                      GDK_RGB_DITHER_NORMAL,
410                      buf,
411                      3*wid);
412   
413   
414   g_free (buf);
415 }
416
417
418 static void
419 color_sample_draw_samples (GtkColorSelection *colorsel)
420 {
421   color_sample_draw_sample (colorsel, 0);
422   color_sample_draw_sample (colorsel, 1);
423 }
424
425 static void
426 color_old_sample_expose(GtkWidget* da, GdkEventExpose* event, GtkColorSelection *colorsel)
427 {
428   color_sample_draw_sample (colorsel, 0);
429 }
430
431
432 static void
433 color_cur_sample_expose(GtkWidget* da, GdkEventExpose* event, GtkColorSelection *colorsel)
434 {
435   color_sample_draw_sample (colorsel, 1);
436 }
437
438 static void
439 color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
440 {
441   static const GtkTargetEntry targets[] = {
442     { "application/x-color", 0 }
443   };
444   ColorSelectionPrivate *priv;
445   priv = colorsel->private_data;
446   
447   gtk_drag_source_set (sample,
448                        GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
449                        targets, 1,
450                        GDK_ACTION_COPY | GDK_ACTION_MOVE);
451   
452   gtk_signal_connect (GTK_OBJECT (sample),
453                       "drag_begin",
454                       GTK_SIGNAL_FUNC (color_sample_drag_begin),
455                       colorsel);
456   if (sample == priv->cur_sample)
457     {
458       
459       gtk_drag_dest_set (sample,
460                          GTK_DEST_DEFAULT_HIGHLIGHT |
461                          GTK_DEST_DEFAULT_MOTION |
462                          GTK_DEST_DEFAULT_DROP,
463                          targets, 1,
464                          GDK_ACTION_COPY);
465       
466       gtk_signal_connect (GTK_OBJECT (sample),
467                           "drag_end",
468                           GTK_SIGNAL_FUNC (color_sample_drag_end),
469                           colorsel);
470     }
471   
472   gtk_signal_connect (GTK_OBJECT (sample),
473                       "drag_data_get",
474                       GTK_SIGNAL_FUNC (color_sample_drag_handle),
475                       colorsel);
476   gtk_signal_connect (GTK_OBJECT (sample),
477                       "drag_data_received",
478                       GTK_SIGNAL_FUNC (color_sample_drop_handle),
479                       colorsel);
480   
481 }
482
483
484 static void
485 color_sample_new (GtkColorSelection *colorsel)
486 {
487   ColorSelectionPrivate *priv;
488   
489   priv = colorsel->private_data;
490   
491   gtk_widget_push_visual(gdk_rgb_get_visual());
492   gtk_widget_push_colormap(gdk_rgb_get_cmap());
493   
494   priv->sample_area = gtk_hbox_new (FALSE, 0);
495   priv->old_sample = gtk_drawing_area_new ();
496   priv->cur_sample = gtk_drawing_area_new ();
497   
498   gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
499                       TRUE, TRUE, 0);
500   gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
501                       TRUE, TRUE, 0);
502   gtk_widget_pop_visual();
503   gtk_widget_pop_colormap();
504   
505   gtk_signal_connect(GTK_OBJECT (priv->old_sample), "expose_event",
506                      GTK_SIGNAL_FUNC (color_old_sample_expose),
507                      colorsel);
508   gtk_signal_connect(GTK_OBJECT (priv->cur_sample), "expose_event",
509                      GTK_SIGNAL_FUNC (color_cur_sample_expose),
510                      colorsel);
511   
512   color_sample_setup_dnd (colorsel, priv->old_sample);
513   color_sample_setup_dnd (colorsel, priv->cur_sample);
514   
515   gtk_widget_show_all (priv->sample_area);
516 }
517
518
519 /*
520  *
521  * The palette area code
522  *
523  */
524 #define CUSTOM_PALETTE_ENTRY_WIDTH   16
525 #define CUSTOM_PALETTE_ENTRY_HEIGHT  16
526
527 static void
528 palette_get_color (GtkWidget *drawing_area, gdouble *color)
529 {
530   gdouble *color_val;
531   
532   g_return_if_fail (color != NULL);
533   
534   color_val = gtk_object_get_data (GTK_OBJECT (drawing_area), "color_val");
535   if (color_val == NULL)
536     {
537       /* Default to white for no good reason */
538       color[0] = 1.0;
539       color[1] = 1.0;
540       color[2] = 1.0;
541       color[3] = 1.0;
542       return;
543     }
544   
545   color[0] = color_val[0];
546   color[1] = color_val[1];
547   color[2] = color_val[2];
548   color[3] = 1.0;
549 }
550
551 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
552 static void
553 palette_paint (GtkWidget    *drawing_area,
554                GdkRectangle *area,
555                gpointer      data)
556 {
557   GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); 
558   ColorSelectionPrivate *priv = colorsel->private_data; 
559
560   if (drawing_area->window == NULL)
561     return;
562   
563   gdk_window_clear_area (drawing_area->window,
564                          area->x,
565                          area->y,
566                          area->width, 
567                          area->height);
568   
569   if (priv->last_palette == drawing_area)
570     {
571       GdkGC *gc;
572       gdouble color[4];
573       
574       palette_get_color (drawing_area, color);
575       
576       if (INTENSITY (color[0], color[1], color[2]) > 0.5)
577         gc = drawing_area->style->black_gc;
578       else
579         gc = drawing_area->style->white_gc;
580
581       gdk_draw_rectangle (drawing_area->window,
582                           gc, FALSE, 0, 0,
583                           drawing_area->allocation.width - 1,
584                           drawing_area->allocation.height - 1);
585     }
586 }
587
588 static void
589 palette_expose (GtkWidget      *drawing_area,
590                 GdkEventExpose *event,
591                 gpointer        data)
592 {
593   if (drawing_area->window == NULL)
594     return;
595   
596   palette_paint (drawing_area, &(event->area), data);
597 }
598
599 static void
600 palette_press (GtkWidget      *drawing_area,
601                GdkEventButton *event,
602                gpointer        data)
603 {
604   GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); 
605   ColorSelectionPrivate *priv = colorsel->private_data; 
606  
607   if (priv->last_palette != NULL) 
608     gtk_widget_queue_clear (priv->last_palette);
609   
610   priv->last_palette = drawing_area;
611
612   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) != 0)
613     {
614       gdouble color[4];
615       palette_get_color (drawing_area, color);
616       gtk_color_selection_set_color (GTK_COLOR_SELECTION (data), color);
617     }
618
619   gtk_widget_queue_clear (priv->last_palette);
620 }
621
622 static void
623 palette_draw (GtkWidget    *drawing_area,
624               GdkRectangle *area,
625               gpointer      data)
626 {
627   palette_paint (drawing_area, area, data);
628 }
629
630 static void
631 palette_unset_color (GtkWidget *drawing_area)
632 {
633   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) == 0)
634     return;
635   
636   gtk_widget_reset_rc_styles (drawing_area);
637   gtk_object_set_data (GTK_OBJECT (drawing_area), "color_set", GINT_TO_POINTER (0));
638 }
639
640 static void
641 palette_drag_begin (GtkWidget      *widget,
642                     GdkDragContext *context,
643                     gpointer        data)
644 {
645   GtkColorSelection *colorsel = data;
646   ColorSelectionPrivate *priv;
647   GtkWidget *window;
648   gdouble colors[4];
649   GdkColor bg;
650   
651   priv = colorsel->private_data;
652   window = gtk_window_new (GTK_WINDOW_POPUP);
653   gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
654   gtk_widget_set_usize (window, 48, 32);
655   gtk_widget_realize (window);
656   gtk_object_set_data_full (GTK_OBJECT (widget),
657                             "gtk-color-selection-drag-window",
658                             window,
659                             (GtkDestroyNotify) gtk_widget_destroy);
660   
661   palette_get_color (widget, colors);
662   bg.red = 0xffff * colors[0];
663   bg.green = 0xffff * colors[1];
664   bg.blue = 0xffff * colors[2];
665   
666   gdk_color_alloc (gtk_widget_get_colormap (window), &bg);
667   gdk_window_set_background (window->window, &bg);
668   
669   gtk_drag_set_icon_widget (context, window, -2, -2);
670 }
671
672 static void
673 palette_drag_handle (GtkWidget        *widget,
674                      GdkDragContext   *context,
675                      GtkSelectionData *selection_data,
676                      guint             info,
677                      guint             time,
678                      gpointer          data)
679 {
680   guint16 vals[4];
681   gdouble colsrc[4];
682   
683   palette_get_color (widget, colsrc);
684   
685   vals[0] = colsrc[COLORSEL_RED] * 0xffff;
686   vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
687   vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
688   vals[3] = 0xffff;
689   
690   gtk_selection_data_set (selection_data,
691                           gdk_atom_intern ("application/x-color", FALSE),
692                           16, (guchar *)vals, 8);
693 }
694
695 static void
696 palette_set_color (GtkWidget         *drawing_area,
697                    GtkColorSelection *colorsel,
698                    gdouble           *color)
699 {
700   GtkRcStyle *rc_style;
701   gdouble *new_color = g_new (double, 4);
702   gdouble *old_color;
703   
704   rc_style = gtk_rc_style_new ();
705   rc_style->bg[GTK_STATE_NORMAL].red = color[0]*65535;
706   rc_style->bg[GTK_STATE_NORMAL].green = color[1]*65535;
707   rc_style->bg[GTK_STATE_NORMAL].blue = color[2]*65535;
708   rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_BG;
709   gtk_rc_style_ref (rc_style);
710   gtk_widget_modify_style (drawing_area, rc_style);
711   
712   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (drawing_area), "color_set")) == 0)
713     {
714       static const GtkTargetEntry targets[] = {
715         { "application/x-color", 0 }
716       };
717       gtk_drag_source_set (drawing_area,
718                            GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
719                            targets, 1,
720                            GDK_ACTION_COPY | GDK_ACTION_MOVE);
721       
722       gtk_signal_connect (GTK_OBJECT (drawing_area),
723                           "drag_begin",
724                           GTK_SIGNAL_FUNC (palette_drag_begin),
725                           colorsel);
726       gtk_signal_connect (GTK_OBJECT (drawing_area),
727                           "drag_data_get",
728                           GTK_SIGNAL_FUNC (palette_drag_handle),
729                           colorsel);
730       
731       gtk_object_set_data (GTK_OBJECT (drawing_area), "color_set", GINT_TO_POINTER (1));
732     }
733   else
734     {
735       old_color = (gdouble *) gtk_object_get_data (GTK_OBJECT (drawing_area), "color_val");
736       if (old_color)
737         {
738           g_free (old_color);
739         }
740     }
741   new_color[0] = color[0];
742   new_color[1] = color[1];
743   new_color[2] = color[2];
744   new_color[3] = 1.0;
745   
746   gtk_object_set_data (GTK_OBJECT (drawing_area), "color_val", new_color);
747 }
748
749 static void
750 palette_drag_end (GtkWidget      *widget,
751                   GdkDragContext *context,
752                   gpointer        data)
753 {
754   gtk_object_set_data (GTK_OBJECT (widget), "gtk-color-selection-drag-window", NULL);
755 }
756
757 static void
758 palette_drop_handle (GtkWidget        *widget,
759                      GdkDragContext   *context,
760                      gint              x,
761                      gint              y,
762                      GtkSelectionData *selection_data,
763                      guint             info,
764                      guint             time,
765                      gpointer          data)
766 {
767   guint16 *vals;
768   gdouble color[4];
769   
770   if (selection_data->length < 0)
771     return;
772   
773   if ((selection_data->format != 16) ||
774       (selection_data->length != 8))
775     {
776       g_warning ("Received invalid color data\n");
777       return;
778     }
779   
780   vals = (guint16 *)selection_data->data;
781   
782   color[0] = (gdouble)vals[0] / 0xffff;
783   color[1] = (gdouble)vals[1] / 0xffff;
784   color[2] = (gdouble)vals[2] / 0xffff;
785   color[3] = (gdouble)vals[3] / 0xffff;
786   palette_set_color (widget, GTK_COLOR_SELECTION (data), color);
787   gtk_color_selection_set_color (GTK_COLOR_SELECTION (data), color);
788 }
789
790 static gint
791 palette_activate (GtkWidget   *widget,
792                   GdkEventKey *event,
793                   gpointer     data)
794 {
795   GtkColorSelection *colorsel = data;
796   ColorSelectionPrivate *priv;
797   
798   if ((event->keyval == ' ') || (event->keyval == GDK_Return))
799     {
800       priv = colorsel->private_data;
801       palette_set_color (widget, GTK_COLOR_SELECTION (data), priv->color);
802     }
803   
804   return TRUE;
805 }
806
807 static GtkWidget*
808 palette_new (GtkColorSelection *colorsel)
809 {
810   GtkWidget *retval;
811   
812   static const GtkTargetEntry targets[] = {
813     { "application/x-color", 0 }
814   };
815   
816   retval = gtk_drawing_area_new ();
817   gtk_object_set_data (GTK_OBJECT (retval), "color_set", GINT_TO_POINTER (0)); 
818   gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK | GDK_EXPOSURE_MASK);
819   
820   gtk_signal_connect (GTK_OBJECT (retval), "draw", palette_draw, colorsel);
821   gtk_signal_connect (GTK_OBJECT (retval), "expose_event", palette_expose, colorsel);
822   gtk_signal_connect (GTK_OBJECT (retval), "button_press_event", palette_press, colorsel);
823   
824   gtk_drag_dest_set (retval,
825                      GTK_DEST_DEFAULT_HIGHLIGHT |
826                      GTK_DEST_DEFAULT_MOTION |
827                      GTK_DEST_DEFAULT_DROP,
828                      targets, 1,
829                      GDK_ACTION_COPY);
830   
831   gtk_signal_connect (GTK_OBJECT (retval), "drag_end", palette_drag_end, NULL);
832   gtk_signal_connect (GTK_OBJECT (retval), "drag_data_received", palette_drop_handle, colorsel);
833   gtk_signal_connect (GTK_OBJECT (retval), "key_press_event", GTK_SIGNAL_FUNC (palette_activate), colorsel);
834   
835   return retval;
836 }
837
838
839 /*
840  *
841  * The actual GtkColorSelection widget
842  *
843  */
844
845 static void
846 initialize_cursor (void)
847 {
848   GdkColor fg, bg;
849   
850   GdkPixmap *pixmap =
851     gdk_bitmap_create_from_data (NULL,
852                                  dropper_bits,
853                                  DROPPER_WIDTH, DROPPER_HEIGHT);
854   GdkPixmap *mask =
855     gdk_bitmap_create_from_data (NULL,
856                                  dropper_mask,
857                                  DROPPER_WIDTH, DROPPER_HEIGHT);
858   
859   gdk_color_white (gdk_colormap_get_system (), &bg);
860   gdk_color_black (gdk_colormap_get_system (), &fg);
861   
862   picker_cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, DROPPER_X_HOT ,DROPPER_Y_HOT);
863   
864   gdk_pixmap_unref (pixmap);
865   gdk_pixmap_unref (mask);
866   
867 }
868
869 static void
870 grab_color_at_mouse (GtkWidget *button,
871                      gint       x_root,
872                      gint       y_root,
873                      gpointer   data)
874 {
875   GdkImage *image;
876   guint32 pixel;
877   GdkVisual *visual;
878   GtkColorSelection *colorsel = data;
879   ColorSelectionPrivate *priv;
880   GdkColormap *colormap = gdk_colormap_get_system ();
881 #if defined (GDK_WINDOWING_X11)
882   XColor xcolor;
883 #endif
884   
885   priv = colorsel->private_data;
886   
887   image = gdk_image_get (GDK_ROOT_PARENT (), x_root, y_root, 1, 1);
888   pixel = gdk_image_get_pixel (image, 0, 0);
889   visual = gdk_colormap_get_visual (colormap);
890   
891   switch (visual->type) {
892   case GDK_VISUAL_DIRECT_COLOR:
893   case GDK_VISUAL_TRUE_COLOR:
894     priv->color[COLORSEL_RED] = (double)((pixel & visual->red_mask)>>visual->red_shift)/((1<<visual->red_prec) - 1);
895     priv->color[COLORSEL_GREEN] = (double)((pixel & visual->green_mask)>>visual->green_shift)/((1<<visual->green_prec) - 1);
896     priv->color[COLORSEL_BLUE] = (double)((pixel & visual->blue_mask)>>visual->blue_shift)/((1<<visual->blue_prec) - 1);
897     break;
898   case GDK_VISUAL_STATIC_GRAY:
899   case GDK_VISUAL_GRAYSCALE:
900     priv->color[COLORSEL_RED] = (double)pixel/((1<<visual->depth) - 1);
901     priv->color[COLORSEL_GREEN] = (double)pixel/((1<<visual->depth) - 1);
902     priv->color[COLORSEL_BLUE] = (double)pixel/((1<<visual->depth) - 1);
903     break;
904 #if defined (GDK_WINDOWING_X11)
905   case GDK_VISUAL_STATIC_COLOR:
906     xcolor.pixel = pixel;
907     XQueryColor (GDK_DISPLAY (), GDK_COLORMAP_XCOLORMAP (colormap), &xcolor);
908     priv->color[COLORSEL_RED] = xcolor.red/65535.0;
909     priv->color[COLORSEL_GREEN] = xcolor.green/65535.0;
910     priv->color[COLORSEL_BLUE] = xcolor.blue/65535.0;
911     break;
912 #endif
913   case GDK_VISUAL_PSEUDO_COLOR:
914     priv->color[COLORSEL_RED] = colormap->colors[pixel].red/(double)0xffffff;
915     priv->color[COLORSEL_GREEN] = colormap->colors[pixel].green/(double)0xffffff;
916     priv->color[COLORSEL_BLUE] = colormap->colors[pixel].blue/(double)0xffffff;
917     break;
918   default:
919     g_assert_not_reached ();
920     break;
921   }
922   
923   gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
924                   priv->color[COLORSEL_GREEN],
925                   priv->color[COLORSEL_BLUE],
926                   &priv->color[COLORSEL_HUE],
927                   &priv->color[COLORSEL_SATURATION],
928                   &priv->color[COLORSEL_VALUE]);
929   update_color (colorsel);
930 }
931
932 static void
933 mouse_motion (GtkWidget      *button,
934               GdkEventMotion *event,
935               gpointer        data)
936 {
937   grab_color_at_mouse (button, event->x_root, event->y_root, data); 
938 }
939
940 static void
941 mouse_release (GtkWidget      *button,
942                GdkEventButton *event,
943                gpointer        data)
944 {
945   GtkColorSelection *colorsel = data;
946   ColorSelectionPrivate *priv;
947   priv = colorsel->private_data;
948   
949   gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_motion, data);
950   gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_release, data);
951   
952   grab_color_at_mouse (button, event->x_root, event->y_root, data);
953   gdk_pointer_ungrab (0);
954 }
955
956 /* Helper Functions */
957 static void
958 mouse_press (GtkWidget      *button,
959              GdkEventButton *event,
960              gpointer        data)
961 {
962   GtkColorSelection *colorsel = data;
963   ColorSelectionPrivate *priv;
964   priv = colorsel->private_data;
965   
966   gtk_signal_connect (GTK_OBJECT (button), "motion_notify_event", mouse_motion, data);
967   gtk_signal_connect (GTK_OBJECT (button), "button_release_event", mouse_release, data);
968   gtk_signal_disconnect_by_func (GTK_OBJECT (button), mouse_press, data); 
969 }
970
971 /* when the button is clicked */
972 static void
973 get_screen_color (GtkWidget *button)
974 {
975   GtkColorSelection *colorsel = gtk_object_get_data (GTK_OBJECT (button), "COLORSEL");
976   ColorSelectionPrivate *priv = colorsel->private_data; 
977   
978   if (picker_cursor == NULL)
979     {
980       initialize_cursor ();
981     }
982   
983   /* Why do we do this? Because the "clicked" signal will be emitted after the "button_released"
984      signal. We don't want to do this stuff again, though, or else it will get trapped here. So, 
985      priv->moving_dropper is initialized to FALSE at the initialization of the colorselector, 
986      it is initialized to true when we start waiting for the user to click the the dropper on a 
987      color, and whenver it is true when this function starts to execute, we set it to false. */
988   if (priv->moving_dropper == FALSE)
989     {
990       priv->moving_dropper = TRUE;
991       gtk_signal_connect (GTK_OBJECT (button), "button_press_event", mouse_press, colorsel); 
992       
993       gdk_pointer_grab (button->window,
994                         FALSE,
995                         GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
996                         NULL,
997                         picker_cursor,
998                         0);
999     }
1000   else
1001     {
1002       priv->moving_dropper = FALSE; 
1003     }
1004 }
1005
1006 void
1007 hex_changed (GtkWidget *hex_entry,
1008              gpointer   data)
1009 {
1010   GtkColorSelection *colorsel;
1011   ColorSelectionPrivate *priv;
1012   GdkColor color;
1013   gchar *text;
1014   
1015   colorsel = GTK_COLOR_SELECTION (data);
1016   priv = colorsel->private_data;
1017   
1018   if (priv->changing)
1019     return;
1020   
1021   text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1);
1022   if (gdk_color_parse (text, &color))
1023     {
1024       priv->color[COLORSEL_RED] = CLAMP (color.red/65280.0, 0.0, 1.0);
1025       priv->color[COLORSEL_GREEN] = CLAMP (color.green/65280.0, 0.0, 1.0);
1026       priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65280.0, 0.0, 1.0);
1027       gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1028                       priv->color[COLORSEL_GREEN],
1029                       priv->color[COLORSEL_BLUE],
1030                       &priv->color[COLORSEL_HUE],
1031                       &priv->color[COLORSEL_SATURATION],
1032                       &priv->color[COLORSEL_VALUE]);
1033       update_color (colorsel);
1034     }
1035   g_free (text);
1036 }
1037
1038 void
1039 hsv_changed (GtkWidget *hsv,
1040              gpointer   data)
1041 {
1042   GtkColorSelection *colorsel;
1043   ColorSelectionPrivate *priv;
1044   
1045   colorsel = GTK_COLOR_SELECTION (data);
1046   priv = colorsel->private_data;
1047   
1048   if (priv->changing)
1049     return;
1050   
1051   gtk_hsv_get_color (GTK_HSV (hsv),
1052                      &priv->color[COLORSEL_HUE],
1053                      &priv->color[COLORSEL_SATURATION],
1054                      &priv->color[COLORSEL_VALUE]);
1055   gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1056                   priv->color[COLORSEL_SATURATION],
1057                   priv->color[COLORSEL_VALUE],
1058                   &priv->color[COLORSEL_RED],
1059                   &priv->color[COLORSEL_GREEN],
1060                   &priv->color[COLORSEL_BLUE]);
1061   update_color (colorsel);
1062 }
1063
1064 void
1065 adjustment_changed (GtkAdjustment *adjustment,
1066                     gpointer       data)
1067 {
1068   GtkColorSelection *colorsel;
1069   ColorSelectionPrivate *priv;
1070   
1071   colorsel = GTK_COLOR_SELECTION (gtk_object_get_data (GTK_OBJECT (adjustment), "COLORSEL"));
1072   priv = colorsel->private_data;
1073   
1074   if (priv->changing)
1075     return;
1076   
1077   switch (GPOINTER_TO_INT (data))
1078     {
1079     case COLORSEL_SATURATION:
1080     case COLORSEL_VALUE:
1081       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1082       gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1083                       priv->color[COLORSEL_SATURATION],
1084                       priv->color[COLORSEL_VALUE],
1085                       &priv->color[COLORSEL_RED],
1086                       &priv->color[COLORSEL_GREEN],
1087                       &priv->color[COLORSEL_BLUE]);
1088       break;
1089     case COLORSEL_HUE:
1090       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360;
1091       gtk_hsv_to_rgb (priv->color[COLORSEL_HUE],
1092                       priv->color[COLORSEL_SATURATION],
1093                       priv->color[COLORSEL_VALUE],
1094                       &priv->color[COLORSEL_RED],
1095                       &priv->color[COLORSEL_GREEN],
1096                       &priv->color[COLORSEL_BLUE]);
1097       break;
1098     case COLORSEL_RED:
1099     case COLORSEL_GREEN:
1100     case COLORSEL_BLUE:
1101       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1102       
1103       gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1104                       priv->color[COLORSEL_GREEN],
1105                       priv->color[COLORSEL_BLUE],
1106                       &priv->color[COLORSEL_HUE],
1107                       &priv->color[COLORSEL_SATURATION],
1108                       &priv->color[COLORSEL_VALUE]);
1109       break;
1110     default:
1111       priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255;
1112       break;
1113     }
1114   update_color (colorsel);
1115 }
1116
1117 void 
1118 opacity_entry_changed (GtkWidget *opacity_entry,
1119                        gpointer   data)
1120 {
1121   GtkColorSelection *colorsel;
1122   ColorSelectionPrivate *priv;
1123   GtkAdjustment *adj;
1124   gchar *text;
1125   
1126   colorsel = GTK_COLOR_SELECTION (data);
1127   priv = colorsel->private_data;
1128   
1129   if (priv->changing)
1130     return;
1131   
1132   text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1);
1133   adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider));
1134   gtk_adjustment_set_value (adj, g_strtod (text, NULL)); 
1135   
1136   update_color (colorsel);
1137   
1138   g_free (text);
1139 }
1140
1141 static void
1142 widget_focus_in (GtkWidget     *drawing_area,
1143                  GdkEventFocus *event,
1144                  gpointer       data)
1145 {
1146   GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data);
1147   ColorSelectionPrivate *priv = colorsel->private_data;
1148   
1149   /* This signal is connected to by all of the widgets except the "Set Color" button
1150    * This will let you add a color to the currently selected palette
1151    */
1152   
1153   priv->last_palette = NULL;
1154 }
1155
1156
1157 static void
1158 make_label_spinbutton (GtkColorSelection *colorsel,
1159                        GtkWidget        **spinbutton,
1160                        gchar             *text,
1161                        GtkWidget         *table,
1162                        gint               i,
1163                        gint               j,
1164                        gint               channel_type)
1165 {
1166   GtkWidget *label;
1167   GtkAdjustment *adjust;
1168   
1169   if (channel_type == COLORSEL_HUE)
1170     {
1171       adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0));
1172     }
1173   else
1174     {
1175       adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0));
1176     }
1177   gtk_object_set_data (GTK_OBJECT (adjust), "COLORSEL", colorsel);
1178   *spinbutton = gtk_spin_button_new (adjust, 10.0, 0);
1179   gtk_signal_connect (GTK_OBJECT (*spinbutton), "focus_in_event", widget_focus_in, colorsel);
1180   gtk_signal_connect (GTK_OBJECT (adjust), "value_changed", adjustment_changed, GINT_TO_POINTER (channel_type));
1181   label = gtk_label_new (text);
1182   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1183   gtk_table_attach_defaults (GTK_TABLE (table), label, i, i+1, j, j+1);
1184   gtk_table_attach_defaults (GTK_TABLE (table), *spinbutton, i+1, i+2, j, j+1);
1185   
1186 }
1187
1188 static void
1189 make_palette_frame (GtkColorSelection *colorsel,
1190                     GtkWidget         *table,
1191                     gint               i,
1192                     gint               j)
1193 {
1194   GtkWidget *frame;
1195   ColorSelectionPrivate *priv;
1196   
1197   priv = colorsel->private_data;
1198   frame = gtk_frame_new (NULL);
1199   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1200   priv->custom_palette[i][j] = palette_new (colorsel);
1201   gtk_widget_set_usize (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, CUSTOM_PALETTE_ENTRY_HEIGHT);
1202   gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]);
1203   gtk_table_attach_defaults (GTK_TABLE (table), frame, i, i+1, j, j+1);
1204 }
1205
1206 /* Set the palette entry [x][y] to be the currently selected one. */
1207 static void 
1208 set_selected_palette (GtkColorSelection *colorsel, int x, int y)
1209 {
1210   ColorSelectionPrivate *priv = colorsel->private_data; 
1211
1212   if (priv->last_palette != NULL) 
1213     gtk_widget_queue_clear (priv->last_palette);
1214
1215   priv->last_palette = priv->custom_palette[x][y]; 
1216
1217   gtk_widget_queue_clear (priv->last_palette);
1218 }
1219
1220 static void
1221 update_color (GtkColorSelection *colorsel)
1222 {
1223   ColorSelectionPrivate *priv = colorsel->private_data;
1224   gchar entryval[12];
1225   gchar opacity_text[32];
1226   gchar *ptr;
1227   
1228   priv->changing = TRUE;
1229   color_sample_draw_samples (colorsel);
1230   
1231   gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel),
1232                      priv->color[COLORSEL_HUE],
1233                      priv->color[COLORSEL_SATURATION],
1234                      priv->color[COLORSEL_VALUE]);
1235   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1236                             (GTK_SPIN_BUTTON (priv->hue_spinbutton)),
1237                             priv->color[COLORSEL_HUE] * 360);
1238   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1239                             (GTK_SPIN_BUTTON (priv->sat_spinbutton)),
1240                             priv->color[COLORSEL_SATURATION] * 255);
1241   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1242                             (GTK_SPIN_BUTTON (priv->val_spinbutton)),
1243                             priv->color[COLORSEL_VALUE] * 255);
1244   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1245                             (GTK_SPIN_BUTTON (priv->red_spinbutton)),
1246                             priv->color[COLORSEL_RED] * 255);
1247   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1248                             (GTK_SPIN_BUTTON (priv->green_spinbutton)),
1249                             priv->color[COLORSEL_GREEN] * 255);
1250   gtk_adjustment_set_value (gtk_spin_button_get_adjustment
1251                             (GTK_SPIN_BUTTON (priv->blue_spinbutton)),
1252                             priv->color[COLORSEL_BLUE] * 255);
1253   gtk_adjustment_set_value (gtk_range_get_adjustment
1254                             (GTK_RANGE (priv->opacity_slider)),
1255                             priv->color[COLORSEL_OPACITY] * 255);
1256   
1257   g_snprintf (opacity_text, 32, "%.0f", priv->color[COLORSEL_OPACITY] * 255);
1258   gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text);
1259   
1260   g_snprintf (entryval, 11, "#%2X%2X%2X",
1261               (guint) (255 * priv->color[COLORSEL_RED]),
1262               (guint) (255 * priv->color[COLORSEL_GREEN]),
1263               (guint) (255 * priv->color[COLORSEL_BLUE]));
1264   
1265   for (ptr = entryval; *ptr; ptr++)
1266     if (*ptr == ' ')
1267       *ptr = '0';
1268   gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval);
1269   priv->changing = FALSE;
1270 }
1271
1272 static void
1273 add_button_pressed (GtkWidget         *button,
1274                     GtkColorSelection *colorsel)
1275 {
1276   ColorSelectionPrivate *priv;
1277   gint i, j;
1278   
1279   priv = colorsel->private_data;
1280   
1281   for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
1282     {
1283       for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
1284         {
1285           /* Either last_palette is set and we're on it, or it's an empty palette */
1286           if ((priv->last_palette && priv->last_palette == priv->custom_palette[i][j]) ||
1287               ((priv->last_palette == NULL) &&
1288                (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (priv->custom_palette[i][j]),
1289                                                       "color_set")) == 0)))
1290             {
1291               palette_set_color (priv->custom_palette[i][j], colorsel, priv->color);
1292
1293               /* forward the selection */
1294               if ((i == GTK_CUSTOM_PALETTE_WIDTH - 1) && (j == GTK_CUSTOM_PALETTE_HEIGHT - 1))
1295                 set_selected_palette (colorsel, 0, 0);
1296               else if (i == GTK_CUSTOM_PALETTE_WIDTH - 1)
1297                 set_selected_palette (colorsel, 0, j + 1);
1298               else
1299                 set_selected_palette (colorsel, i + 1, j);
1300
1301               return;
1302             }
1303         }
1304     }
1305
1306   /* the palette is totally full.  Add to the first one totally arbitrarily */
1307   palette_set_color (priv->custom_palette[0][0], colorsel, priv->color);
1308
1309   /* forward the selection */
1310   set_selected_palette (colorsel, 1, 0);
1311 }
1312
1313 GtkType
1314 gtk_color_selection_get_type (void)
1315 {
1316   static GtkType color_selection_type = 0;
1317   
1318   if (!color_selection_type)
1319     {
1320       static const GtkTypeInfo color_selection_info =
1321       {
1322         "GtkColorSelection",
1323         sizeof (GtkColorSelection),
1324         sizeof (GtkColorSelectionClass),
1325         (GtkClassInitFunc) gtk_color_selection_class_init,
1326         (GtkObjectInitFunc) gtk_color_selection_init,
1327         /* reserved_1 */ NULL,
1328         /* reserved_2 */ NULL,
1329         (GtkClassInitFunc) NULL,
1330       };
1331       
1332       color_selection_type = gtk_type_unique (GTK_TYPE_VBOX, &color_selection_info);
1333     }
1334   
1335   return color_selection_type;
1336 }
1337
1338 static void
1339 gtk_color_selection_class_init (GtkColorSelectionClass *klass)
1340 {
1341   GtkObjectClass *object_class;
1342   
1343   object_class = (GtkObjectClass*) klass;
1344   
1345   parent_class = gtk_type_class (GTK_TYPE_VBOX);
1346   
1347   color_selection_signals[COLOR_CHANGED] =
1348     gtk_signal_new ("color_changed",
1349                     GTK_RUN_FIRST,
1350                     GTK_CLASS_TYPE (object_class),
1351                     GTK_SIGNAL_OFFSET (GtkColorSelectionClass, color_changed),
1352                     gtk_marshal_NONE__NONE,
1353                     GTK_TYPE_NONE, 0);
1354   
1355   
1356   gtk_object_class_add_signals (object_class, color_selection_signals, LAST_SIGNAL);
1357   
1358   object_class->destroy = gtk_color_selection_destroy;
1359 }
1360
1361 /* widget functions */
1362 static void
1363 gtk_color_selection_init (GtkColorSelection *colorsel)
1364 {
1365   GtkWidget *top_hbox;
1366   GtkWidget *top_right_vbox;
1367   GtkWidget *table, *label, *hbox, *frame, *vbox;
1368   GtkAdjustment *adjust;
1369   GdkPixmap *dropper_pixmap;
1370   GtkWidget *dropper_image;
1371   GtkWidget *button;
1372   GdkBitmap *mask = NULL;
1373   gint i, j;
1374   ColorSelectionPrivate *priv;
1375   
1376   priv = colorsel->private_data = g_new0 (ColorSelectionPrivate, 1);
1377   priv->changing = FALSE;
1378   priv->default_set = FALSE;
1379   priv->last_palette = NULL;
1380   priv->moving_dropper = FALSE;
1381   
1382   gtk_box_set_spacing (GTK_BOX (colorsel), 4);
1383   top_hbox = gtk_hbox_new (FALSE, 8);
1384   gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
1385   
1386   vbox = gtk_vbox_new (FALSE, 4);
1387   priv->triangle_colorsel = gtk_hsv_new ();
1388   gtk_signal_connect (GTK_OBJECT (priv->triangle_colorsel), "changed", hsv_changed, colorsel);
1389   gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
1390   gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
1391   gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
1392   
1393   hbox = gtk_hbox_new (FALSE, 4);
1394   gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1395   
1396   frame = gtk_frame_new (NULL);
1397   gtk_widget_set_usize (frame, -1, 30);
1398   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1399   color_sample_new (colorsel);
1400   gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
1401   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1402   
1403   button = gtk_button_new ();
1404   gtk_signal_connect (GTK_OBJECT (button), "focus_in_event", widget_focus_in, colorsel);
1405   gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
1406   gtk_object_set_data (GTK_OBJECT (button), "COLORSEL", colorsel); 
1407   gtk_signal_connect (GTK_OBJECT (button), "clicked", get_screen_color, NULL);
1408   dropper_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, gtk_widget_get_colormap (button), &mask, NULL, picker);
1409   dropper_image = gtk_pixmap_new (dropper_pixmap, mask);
1410   gtk_container_add (GTK_CONTAINER (button), dropper_image);
1411   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1412   
1413   top_right_vbox = gtk_vbox_new (FALSE, 4);
1414   gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
1415   table = gtk_table_new (8, 6, FALSE);
1416   gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
1417   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
1418   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
1419   
1420   make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("Hue:"), table, 0, 0, COLORSEL_HUE);
1421   make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("Saturation:"), table, 0, 1, COLORSEL_SATURATION);
1422   make_label_spinbutton (colorsel, &priv->val_spinbutton, _("Value:"), table, 0, 2, COLORSEL_VALUE);
1423   make_label_spinbutton (colorsel, &priv->red_spinbutton, _("Red:"), table, 6, 0, COLORSEL_RED);
1424   make_label_spinbutton (colorsel, &priv->green_spinbutton, _("Green:"), table, 6, 1, COLORSEL_GREEN);
1425   make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("Blue:"), table, 6, 2, COLORSEL_BLUE);
1426   gtk_table_attach_defaults (GTK_TABLE (table), gtk_hseparator_new (), 0, 8, 3, 4); 
1427   
1428   priv->opacity_label = gtk_label_new (_("Opacity:")); 
1429   gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5); 
1430   gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_label, 0, 1, 4, 5); 
1431   adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0)); 
1432   gtk_object_set_data (GTK_OBJECT (adjust), "COLORSEL", colorsel); 
1433   priv->opacity_slider = gtk_hscale_new (adjust); 
1434   gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
1435   gtk_signal_connect (GTK_OBJECT(adjust), "value_changed", adjustment_changed, GINT_TO_POINTER (COLORSEL_OPACITY));
1436   gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_slider, 1, 7, 4, 5); 
1437   priv->opacity_entry = gtk_entry_new (); 
1438   gtk_widget_set_usize (priv->opacity_entry, 40, 0); 
1439   gtk_signal_connect (GTK_OBJECT (priv->opacity_entry), "focus_in_event", widget_focus_in, colorsel);
1440   gtk_signal_connect (GTK_OBJECT (priv->opacity_entry), "activate", opacity_entry_changed, colorsel);
1441   gtk_table_attach_defaults (GTK_TABLE (table), priv->opacity_entry, 7, 8, 4, 5);
1442   
1443   label = gtk_label_new (_("Hex Value:"));
1444   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 5, 6);
1445   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
1446   priv->hex_entry = gtk_entry_new ();
1447   gtk_signal_connect (GTK_OBJECT (priv->hex_entry), "activate", hex_changed, colorsel);
1448   gtk_widget_set_usize (priv->hex_entry, 75, -1);  
1449   gtk_table_set_col_spacing (GTK_TABLE (table), 3, 15);
1450   gtk_table_attach_defaults (GTK_TABLE (table), priv->hex_entry, 1, 5, 5, 6);
1451   
1452   /* Set up the palette */
1453   table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE);
1454   gtk_table_set_row_spacings (GTK_TABLE (table), 1);
1455   gtk_table_set_col_spacings (GTK_TABLE (table), 1);
1456   for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
1457     {
1458       for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
1459         {
1460           make_palette_frame (colorsel, table, i, j);
1461         }
1462     }
1463   set_selected_palette (colorsel, 0, 0);
1464   priv->palette_frame = gtk_frame_new (_("Custom Palette"));
1465   gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
1466   vbox = gtk_vbox_new (FALSE, 4);
1467   gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox);
1468   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
1469   button = gtk_button_new_with_label (_("Set Color"));
1470   gtk_signal_connect (GTK_OBJECT (button), "clicked", add_button_pressed, colorsel);
1471   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1472   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
1473   
1474   gtk_widget_show_all (top_hbox);
1475   
1476   if (priv->use_opacity == FALSE)
1477     {
1478       gtk_widget_hide (priv->opacity_label);
1479       gtk_widget_hide (priv->opacity_slider);
1480       gtk_widget_hide (priv->opacity_entry);
1481     }
1482   
1483   if (priv->use_palette == FALSE)
1484     {
1485       gtk_widget_hide (priv->palette_frame);
1486     }
1487 }
1488
1489 static void
1490 gtk_color_selection_destroy (GtkObject *object)
1491 {
1492   GtkColorSelection *cselection = GTK_COLOR_SELECTION (object);
1493   
1494   if (cselection->private_data)
1495     {
1496       g_free (cselection->private_data);
1497       cselection->private_data = NULL;
1498     }
1499   
1500   GTK_OBJECT_CLASS (parent_class)->destroy (object);
1501 }
1502
1503
1504
1505 /**
1506  * gtk_color_selection_new:
1507  * @void: 
1508  * 
1509  * Creates a new GtkColorSelection.
1510  * 
1511  * Return value: The new GtkColorSelection.
1512  **/
1513 GtkWidget *
1514 gtk_color_selection_new (void)
1515 {
1516   GtkColorSelection *colorsel;
1517   ColorSelectionPrivate *priv;
1518   gdouble color[4];
1519   color[0] = 1.0;
1520   color[1] = 1.0;
1521   color[2] = 1.0;
1522   color[3] = 1.0;
1523   
1524   colorsel = gtk_type_new (GTK_TYPE_COLOR_SELECTION);
1525   priv = colorsel->private_data;
1526   gtk_color_selection_set_color (colorsel, color);
1527   gtk_color_selection_set_use_opacity (colorsel, FALSE);
1528   
1529   /* We want to make sure that default_set is FALSE */
1530   /* This way the user can still set it */
1531   priv->default_set = FALSE;
1532   
1533   return GTK_WIDGET (colorsel);
1534 }
1535
1536
1537 void
1538 gtk_color_selection_set_update_policy (GtkColorSelection *colorsel,
1539                                        GtkUpdateType      policy)
1540 {
1541   g_return_if_fail (colorsel != NULL);
1542   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1543   /* */
1544   g_warning (G_STRLOC ": This function is deprecated.");
1545 }
1546
1547 /**
1548  * gtk_color_selection_get_use_opacity:
1549  * @colorsel: A GtkColorSelection.
1550  * 
1551  * Determines whether the colorsel can use opacity.
1552  * 
1553  * Return value: TRUE if the @colorsel uses opacity.  FALSE if it does't.
1554  **/
1555 gboolean
1556 gtk_color_selection_get_use_opacity (GtkColorSelection *colorsel)
1557 {
1558   ColorSelectionPrivate *priv;
1559   
1560   g_return_val_if_fail (colorsel != NULL, FALSE);
1561   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1562   
1563   priv = colorsel->private_data;
1564   
1565   return priv->use_opacity;
1566 }
1567
1568 /**
1569  * gtk_color_selection_set_use_opacity:
1570  * @colorsel: A GtkColorSelection.
1571  * @use_opacity: TRUE if @colorsel can set the opacity, FALSE otherwise.
1572  *
1573  * Sets the @colorsel to use or not use opacity.
1574  * 
1575  **/
1576 void
1577 gtk_color_selection_set_use_opacity (GtkColorSelection *colorsel,
1578                                      gboolean           use_opacity)
1579 {
1580   ColorSelectionPrivate *priv;
1581   
1582   g_return_if_fail (colorsel != NULL);
1583   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1584   
1585   priv = colorsel->private_data;
1586   use_opacity = use_opacity != FALSE;
1587   
1588   if (priv->use_opacity != use_opacity)
1589     {
1590       priv->use_opacity = use_opacity;
1591       if (use_opacity)
1592         {
1593           gtk_widget_show (priv->opacity_slider);
1594           gtk_widget_show (priv->opacity_label);
1595           gtk_widget_show (priv->opacity_entry);
1596         }
1597       else
1598         {
1599           gtk_widget_hide (priv->opacity_slider);
1600           gtk_widget_hide (priv->opacity_label);
1601           gtk_widget_hide (priv->opacity_entry);
1602         }
1603       color_sample_draw_samples (colorsel);
1604     }
1605 }
1606
1607 /**
1608  * gtk_color_selection_get_use_palette:
1609  * @colorsel: A GtkColorSelection.
1610  * 
1611  * Determines whether the palette is used.
1612  * 
1613  * Return value: TRUE if the palette is used.  FALSE if it isn't.
1614  **/
1615 gboolean
1616 gtk_color_selection_get_use_palette (GtkColorSelection *colorsel)
1617 {
1618   ColorSelectionPrivate *priv;
1619   
1620   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1621   
1622   priv = colorsel->private_data;
1623   
1624   return priv->use_palette;
1625 }
1626
1627 /**
1628  * gtk_color_selection_set_use_palette:
1629  * @colorsel: A GtkColorSelection.
1630  * @use_palette: TRUE if palette is to be visible, FALSE otherwise.
1631  *
1632  * Shows and hides the palette based upon the value of @use_palette.
1633  * 
1634  **/
1635 void
1636 gtk_color_selection_set_use_palette (GtkColorSelection *colorsel,
1637                                      gboolean           use_palette)
1638 {
1639   ColorSelectionPrivate *priv;
1640   g_return_if_fail (colorsel != NULL);
1641   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1642   
1643   priv = colorsel->private_data;
1644   use_palette = use_palette != FALSE;
1645   
1646   if (priv->use_palette != use_palette)
1647     {
1648       priv->use_palette = use_palette;
1649       if (use_palette)
1650         gtk_widget_show (priv->palette_frame);
1651       else
1652         gtk_widget_hide (priv->palette_frame);
1653     }
1654 }
1655
1656 /**
1657  * gtk_color_selection_set_color:
1658  * @colorsel: A GtkColorSelection.
1659  * @color: A color to set the current color with.
1660  *
1661  * Sets the current color to be @color.  The first time this is called, it will
1662  * also set the original color to be @color too.
1663  * 
1664  **/
1665 void
1666 gtk_color_selection_set_color (GtkColorSelection    *colorsel,
1667                                gdouble              *color)
1668 {
1669   ColorSelectionPrivate *priv;
1670   gint i;
1671   
1672   g_return_if_fail (colorsel != NULL);
1673   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1674   
1675   priv = colorsel->private_data;
1676   priv->changing = TRUE;
1677   priv->color[COLORSEL_RED] = color[0];
1678   priv->color[COLORSEL_GREEN] = color[1];
1679   priv->color[COLORSEL_BLUE] = color[2];
1680   priv->color[COLORSEL_OPACITY] = color[3];
1681   gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
1682                   priv->color[COLORSEL_GREEN],
1683                   priv->color[COLORSEL_BLUE],
1684                   &priv->color[COLORSEL_HUE],
1685                   &priv->color[COLORSEL_SATURATION],
1686                   &priv->color[COLORSEL_VALUE]);
1687   if (priv->default_set == FALSE)
1688     {
1689       for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
1690         priv->old_color[i] = priv->color[i];
1691     }
1692   update_color (colorsel);
1693   priv->default_set = TRUE;
1694 }
1695
1696 /**
1697  * gtk_color_selection_get_color:
1698  * @colorsel: A GtkColorSelection.
1699  * @color: A color to fill in with the current color.
1700  *
1701  * Sets @color to be the current color in the GtkColorSelection widget.
1702  * 
1703  **/
1704 void
1705 gtk_color_selection_get_color (GtkColorSelection *colorsel,
1706                                gdouble           *color)
1707 {
1708   ColorSelectionPrivate *priv;
1709   
1710   g_return_if_fail (colorsel != NULL);
1711   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1712   
1713   priv = colorsel->private_data;
1714   color[0] = priv->color[COLORSEL_RED];
1715   color[1] = priv->color[COLORSEL_GREEN];
1716   color[2] = priv->color[COLORSEL_BLUE];
1717   color[3] = priv->use_opacity ? priv->color[COLORSEL_OPACITY] : 1.0;
1718 }
1719
1720 /**
1721  * gtk_color_selection_get_old_color:
1722  * @colorsel: A GtkColorSelection.
1723  * @color: A color to set the original color with.
1724  *
1725  * Sets the 'original' color to be @color.  This function should be called with
1726  * some hesitations, as it might seem confusing to have that color change.
1727  * Calling gtk_color_selection_set_color will also set this color the first
1728  * time it is called.
1729  * 
1730  **/
1731 void
1732 gtk_color_selection_set_old_color (GtkColorSelection *colorsel,
1733                                    gdouble          *color)
1734 {
1735   ColorSelectionPrivate *priv;
1736   
1737   g_return_if_fail (colorsel != NULL);
1738   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1739   
1740   priv = colorsel->private_data;
1741   priv->changing = TRUE;
1742   priv->old_color[COLORSEL_RED] = color[0];
1743   priv->old_color[COLORSEL_GREEN] = color[1];
1744   priv->old_color[COLORSEL_BLUE] = color[2];
1745   priv->old_color[COLORSEL_OPACITY] = color[3];
1746   gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED],
1747                   priv->old_color[COLORSEL_GREEN],
1748                   priv->old_color[COLORSEL_BLUE],
1749                   &priv->old_color[COLORSEL_HUE],
1750                   &priv->old_color[COLORSEL_SATURATION],
1751                   &priv->old_color[COLORSEL_VALUE]);
1752   color_sample_draw_samples (colorsel);
1753   priv->default_set = TRUE;
1754 }
1755
1756 /**
1757  * gtk_color_selection_get_old_color:
1758  * @colorsel: A GtkColorSelection.
1759  * @color: A color to fill in with the original color value.
1760  *
1761  * Fills @color in with the original color value.
1762  * 
1763  **/
1764 void
1765 gtk_color_selection_get_old_color (GtkColorSelection *colorsel,
1766                                    gdouble           *color)
1767 {
1768   ColorSelectionPrivate *priv;
1769   
1770   g_return_if_fail (colorsel != NULL);
1771   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1772   
1773   priv = colorsel->private_data;
1774   color[0] = priv->old_color[COLORSEL_RED];
1775   color[1] = priv->old_color[COLORSEL_GREEN];
1776   color[2] = priv->old_color[COLORSEL_BLUE];
1777   color[3] = priv->use_opacity ? priv->old_color[COLORSEL_OPACITY] : 1.0;
1778 }
1779
1780 /**
1781  * gtk_color_selection_set_palette_color:
1782  * @colorsel: A GtkColorSelection.
1783  * @x: The x coordinate of the palette.
1784  * @y: The y coordinate of the palette.
1785  * @color: A color to set the palette with.
1786  *
1787  * Set the palette located at (@x, @y) to have @color set as its color.
1788  * 
1789  **/
1790 void
1791 gtk_color_selection_set_palette_color (GtkColorSelection   *colorsel,
1792                                        gint                 x,
1793                                        gint                 y,
1794                                        gdouble             *color)
1795 {
1796   ColorSelectionPrivate *priv;
1797   
1798   g_return_if_fail (colorsel != NULL);
1799   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1800   g_return_if_fail (x >= 0 && y >= 0 && x < GTK_CUSTOM_PALETTE_WIDTH && y < GTK_CUSTOM_PALETTE_HEIGHT);
1801   
1802   priv = colorsel->private_data;
1803   palette_set_color (priv->custom_palette[x][y], colorsel, color);
1804 }
1805
1806 /**
1807  * gtk_color_selection_get_palette_color:
1808  * @colorsel: A GtkColorSelection.
1809  * @x: The x coordinate of the palette.
1810  * @y: The y coordinate of the palette.
1811  * @color: A color to fill in with the color value.
1812  * 
1813  * Set @color to have the color found in the palette located at (@x, @y).  If
1814  * the palette is unset, it will leave the color unset.
1815  * 
1816  * Return value: TRUE if the palette located at (@x, @y) has a color set.  FALSE
1817  * if it doesn't.
1818  **/
1819 gboolean
1820 gtk_color_selection_get_palette_color (GtkColorSelection   *colorsel,
1821                                        gint                 x,
1822                                        gint                 y,
1823                                        gdouble             *color)
1824 {
1825   ColorSelectionPrivate *priv;
1826   
1827   g_return_val_if_fail (colorsel != NULL, FALSE);
1828   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1829   g_return_val_if_fail (x >= 0 && y >= 0 && x < GTK_CUSTOM_PALETTE_WIDTH && y < GTK_CUSTOM_PALETTE_HEIGHT, FALSE);
1830   
1831   priv = colorsel->private_data;
1832   
1833   if (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (priv->custom_palette[x][y]), "color_set")) == 0)
1834     return FALSE;
1835   
1836   palette_get_color (priv->custom_palette[x][y], color);
1837   return TRUE;
1838 }
1839
1840 /**
1841  * gtk_color_selection_unset_palette_color:
1842  * @colorsel: A GtkColorSelection.
1843  * @x: The x coordinate of the palette.
1844  * @y: The y coordinate of the palette.
1845  *
1846  * Change the palette located at (@x, @y) to have no color set.
1847  * 
1848  **/
1849 void
1850 gtk_color_selection_unset_palette_color (GtkColorSelection   *colorsel,
1851                                          gint                 x,
1852                                          gint                 y)
1853 {
1854   ColorSelectionPrivate *priv;
1855   
1856   g_return_if_fail (colorsel != NULL);
1857   g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel));
1858   g_return_if_fail (x >= 0 && y >= 0 && x < GTK_CUSTOM_PALETTE_WIDTH && y < GTK_CUSTOM_PALETTE_HEIGHT);
1859   
1860   priv = colorsel->private_data;
1861   palette_unset_color (priv->custom_palette[x][y]);
1862 }
1863
1864 /**
1865  * gtk_color_selection_is_adjusting:
1866  * @colorsel: A GtkColorSelection.
1867  *
1868  * Gets the current state of the @colorsel.
1869  *
1870  * Return value: TRUE if the user is currently dragging a color around, and FALSE
1871  * if the selection has stopped.
1872  **/
1873 gboolean
1874 gtk_color_selection_is_adjusting (GtkColorSelection *colorsel)
1875 {
1876   ColorSelectionPrivate *priv;
1877   
1878   g_return_val_if_fail (colorsel != NULL, FALSE);
1879   g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE);
1880   
1881   priv = colorsel->private_data;
1882   
1883   return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel)));
1884 }