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