home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / palette.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  85.5 KB  |  3,265 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifdef HAVE_DIRENT_H
  28. #include <sys/types.h>
  29. #include <dirent.h>
  30. #endif
  31. #include <sys/stat.h>
  32. #include <sys/types.h>
  33.  
  34. #include <gtk/gtk.h>
  35.  
  36. #include "apptypes.h"
  37.  
  38. #include "appenv.h"
  39. #include "color_area.h"
  40. #include "color_notebook.h"
  41. #include "datafiles.h"
  42. #include "gimpcontext.h"
  43. #include "gimpdnd.h"
  44. #include "gimprc.h"
  45. #include "gimpui.h"
  46. #include "gradient_header.h"
  47. #include "gradient_select.h"
  48. #include "palette.h"
  49. #include "paletteP.h"
  50. #include "palette_entries.h"
  51. #include "session.h"
  52. #include "palette_select.h"
  53. #include "dialog_handler.h"
  54.  
  55. #include "libgimp/gimpenv.h"
  56.  
  57. #include "libgimp/gimpintl.h"
  58.  
  59. #include "pixmaps/zoom_in.xpm"
  60. #include "pixmaps/zoom_out.xpm"
  61.  
  62. #define ENTRY_WIDTH  12
  63. #define ENTRY_HEIGHT 10
  64. #define SPACING       1
  65. #define COLUMNS      16
  66. #define ROWS         11
  67.  
  68. #define PREVIEW_WIDTH  ((ENTRY_WIDTH * COLUMNS) + (SPACING * (COLUMNS + 1)))
  69. #define PREVIEW_HEIGHT ((ENTRY_HEIGHT * ROWS) + (SPACING * (ROWS + 1)))
  70.  
  71. #define PALETTE_EVENT_MASK GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | \
  72.                            GDK_ENTER_NOTIFY_MASK
  73.  
  74. /* New palette code... */
  75.  
  76. #define IMPORT_PREVIEW_WIDTH  80
  77. #define IMPORT_PREVIEW_HEIGHT 80
  78. #define MAX_IMAGE_COLORS      (10000*2)
  79.  
  80. typedef enum
  81. {
  82.   GRAD_IMPORT = 0,
  83.   IMAGE_IMPORT = 1,
  84.   INDEXED_IMPORT = 2
  85. } ImportType;
  86.  
  87. typedef struct _ImportDialog ImportDialog;
  88.  
  89. struct _ImportDialog
  90. {
  91.   GtkWidget     *dialog;
  92.   GtkWidget     *preview;
  93.   GtkWidget     *entry;
  94.   GtkWidget     *select_area;
  95.   GtkWidget     *select;
  96.   GtkWidget     *image_list;
  97.   GtkWidget     *image_menu_item_image;
  98.   GtkWidget     *image_menu_item_indexed;
  99.   GtkWidget     *image_menu_item_gradient;
  100.   GtkWidget     *optionmenu1_menu;
  101.   GtkWidget     *type_option;
  102.   GtkWidget     *threshold_scale;
  103.   GtkWidget     *threshold_text;
  104.   GtkAdjustment *threshold;
  105.   GtkAdjustment *sample;
  106.   ImportType     import_type;
  107.   GimpImage     *gimage;
  108. };
  109.  
  110. typedef struct _PaletteDialog PaletteDialog;
  111.  
  112. struct _PaletteDialog
  113. {
  114.   GtkWidget      *shell;
  115.  
  116.   GtkWidget      *color_area;
  117.   GtkWidget      *scrolled_window;
  118.   GtkWidget      *color_name;
  119.   GtkWidget      *clist;
  120.  
  121.   GtkWidget      *popup_menu;
  122.   GtkWidget      *delete_menu_item;
  123.   GtkWidget      *edit_menu_item;
  124.  
  125.   ColorNotebook  *color_notebook;
  126.   gboolean        color_notebook_active;
  127.  
  128.   PaletteEntries *entries;
  129.   PaletteEntry   *color;
  130.   PaletteEntry   *dnd_color;
  131.  
  132.   GdkGC          *gc;
  133.   guint           entry_sig_id;
  134.   gfloat          zoom_factor;  /* range from 0.1 to 4.0 */
  135.   gint            col_width;
  136.   gint            last_width;
  137.   gint            columns;
  138.   gboolean        freeze_update;
  139.   gboolean        columns_valid;
  140. };
  141.  
  142. /*  local function prototypes  */
  143. static void  palette_entry_free    (PaletteEntry *);
  144. static void  palette_entries_free  (PaletteEntries *);
  145. static void  palette_entries_load  (gchar *);
  146. static void  palette_entries_save  (PaletteEntries *, gchar *);
  147. static void  palette_save_palettes (void);
  148.  
  149. static void  palette_entries_list_insert    (PaletteEntries *entries);
  150.  
  151. static void  palette_dialog_draw_entries    (PaletteDialog *palette,
  152.                          gint           row_start,
  153.                          gint           column_highlight);
  154. static void  palette_dialog_redraw          (PaletteDialog *palette);
  155. static void  palette_dialog_scroll_top_left (PaletteDialog *palette);
  156.  
  157. static PaletteDialog * palette_dialog_new        (gboolean       editor);
  158. static ImportDialog  * palette_import_dialog_new (PaletteDialog *palette);
  159.  
  160.  
  161. GSList                *palette_entries_list    = NULL;
  162. PaletteDialog         *top_level_edit_palette  = NULL;
  163. PaletteDialog         *top_level_palette       = NULL;
  164.  
  165. static PaletteEntries *default_palette_entries = NULL;
  166. static gint            num_palette_entries     = 0;
  167. static ImportDialog   *import_dialog           = NULL;
  168.  
  169.  
  170. /*  dnd stuff  */
  171. static GtkTargetEntry color_palette_target_table[] =
  172. {
  173.   GIMP_TARGET_COLOR
  174. };
  175. static guint n_color_palette_targets = (sizeof (color_palette_target_table) /
  176.                     sizeof (color_palette_target_table[0]));
  177.  
  178. /*  public functions  ********************************************************/
  179.  
  180. void
  181. palettes_init (gboolean no_data)
  182. {
  183.   if (!no_data)
  184.     datafiles_read_directories (palette_path, palette_entries_load, 0);
  185.  
  186.   if (!default_palette_entries && palette_entries_list)
  187.     default_palette_entries = palette_entries_list->data;
  188. }
  189.  
  190. void
  191. palettes_free (void)
  192. {
  193.   PaletteEntries *entries;
  194.   GSList *list;
  195.  
  196.   for (list = palette_entries_list; list; list = g_slist_next (list))
  197.     {
  198.       entries = (PaletteEntries *) list->data;
  199.  
  200.       /*  If the palette has been changed, save it, if possible  */
  201.       if (entries->changed)
  202.     /*  save the palette  */
  203.     palette_entries_save (entries, entries->filename);
  204.  
  205.       palette_entries_free (entries);
  206.     }
  207.  
  208.   g_slist_free (palette_entries_list);
  209.  
  210.   num_palette_entries = 0;
  211.   palette_entries_list = NULL;
  212. }
  213.  
  214. void 
  215. palette_dialog_create (void)
  216. {
  217.   if (top_level_palette == NULL)
  218.     {
  219.       top_level_palette = palette_dialog_new (TRUE);
  220.       session_set_window_geometry (top_level_palette->shell,
  221.                    &palette_session_info, TRUE);
  222.       dialog_register (top_level_palette->shell);
  223.  
  224.       gtk_widget_show (top_level_palette->shell);
  225.     }
  226.   else
  227.     {
  228.       if (! GTK_WIDGET_VISIBLE (top_level_palette->shell))
  229.     {
  230.       gtk_widget_show (top_level_palette->shell);
  231.     }
  232.       else
  233.     {
  234.       gdk_window_raise (top_level_palette->shell->window);
  235.     }
  236.     }
  237. }
  238.  
  239. void
  240. palette_dialog_free (void)
  241. {
  242.   if (top_level_edit_palette) 
  243.     {
  244.       if (import_dialog)
  245.     {
  246.       gtk_widget_destroy (import_dialog->dialog);
  247.       g_free (import_dialog);
  248.       import_dialog = NULL;
  249.     }
  250.  
  251.       gdk_gc_destroy (top_level_edit_palette->gc); 
  252.       
  253.       if (top_level_edit_palette->color_notebook) 
  254.     color_notebook_free (top_level_edit_palette->color_notebook); 
  255.  
  256.       g_free (top_level_edit_palette); 
  257.       top_level_edit_palette = NULL; 
  258.     }
  259.  
  260.   if (top_level_palette)
  261.     {
  262.       gdk_gc_destroy (top_level_palette->gc); 
  263.       session_get_window_info (top_level_palette->shell,
  264.                    &palette_session_info);  
  265.  
  266.       if (top_level_palette->color_notebook) 
  267.     color_notebook_free (top_level_palette->color_notebook); 
  268.  
  269.       g_free (top_level_palette);
  270.       top_level_palette = NULL;
  271.     }
  272. }
  273.  
  274. /*  palette entries functions  ***********************************************/
  275.  
  276. static PaletteEntries *
  277. palette_entries_new (gchar *palette_name)
  278. {
  279.   PaletteEntries *entries = NULL;
  280.   GList *pal_path;
  281.   gchar *pal_dir;
  282.  
  283.   if (!palette_name || !palette_path)
  284.     return NULL;
  285.  
  286.   pal_path = gimp_path_parse (palette_path, 16, TRUE, NULL);
  287.   pal_dir  = gimp_path_get_user_writable_dir (pal_path);
  288.   gimp_path_free (pal_path);
  289.  
  290.   entries = g_new (PaletteEntries, 1);
  291.  
  292.   if (pal_dir)
  293.     {
  294.       entries->filename = g_strdup_printf ("%s%s", pal_dir, palette_name);
  295.       g_free (pal_dir);
  296.     }
  297.   else
  298.     {
  299.       entries->filename = NULL;
  300.     }
  301.  
  302.   entries->name     = palette_name;  /*  this memory is ours  */
  303.   entries->colors   = NULL;
  304.   entries->n_colors = 0;
  305.   entries->changed  = TRUE;
  306.   entries->pixmap   = NULL;
  307.  
  308.   palette_entries_list_insert (entries);
  309.  
  310.   palette_save_palettes ();
  311.  
  312.   return entries;
  313. }
  314.  
  315. static void
  316. palette_entries_free (PaletteEntries *entries)
  317. {
  318.   PaletteEntry *entry;
  319.   GSList *list;
  320.  
  321.   for (list = entries->colors; list; list = g_slist_next (list))
  322.     {
  323.       entry = (PaletteEntry *) list->data;
  324.  
  325.       palette_entry_free (entry);
  326.     }
  327.  
  328.   g_slist_free (entries->colors);
  329.  
  330.   if (entries->name)
  331.     g_free (entries->name);
  332.  
  333.   if (entries->filename)
  334.     g_free (entries->filename);
  335.  
  336.   if (entries->pixmap)
  337.     gdk_pixmap_unref (entries->pixmap);
  338.  
  339.   g_free (entries);
  340. }
  341.  
  342. static PaletteEntry *
  343. palette_entries_add_entry (PaletteEntries *entries,
  344.                gchar          *name,
  345.                gint            r,
  346.                gint            g,
  347.                gint            b)
  348. {
  349.   PaletteEntry *entry;
  350.  
  351.   if (entries)
  352.     {
  353.       entry = g_new (PaletteEntry, 1);
  354.  
  355.       entry->color[0] = r;
  356.       entry->color[1] = g;
  357.       entry->color[2] = b;
  358.       entry->name     = g_strdup (name ? name : _("Untitled"));
  359.       entry->position = entries->n_colors;
  360.  
  361.       entries->colors    = g_slist_append (entries->colors, entry);
  362.       entries->n_colors += 1;
  363.       entries->changed   = TRUE;
  364.       
  365.       return entry;
  366.     }
  367.  
  368.   return NULL;
  369. }
  370.  
  371. static void
  372. palette_entries_load (gchar *filename)
  373. {
  374.   PaletteEntries *entries;
  375.   gchar  str[512];
  376.   gchar *tok;
  377.   FILE  *fp;
  378.   gint   r, g, b;
  379.   gint   linenum;
  380.  
  381.   r = g = b = 0;
  382.  
  383.   entries = g_new (PaletteEntries, 1);
  384.  
  385.   entries->filename = g_strdup (filename);
  386.   entries->name     = g_strdup (g_basename (filename));
  387.   entries->colors   = NULL;
  388.   entries->n_colors = 0;
  389.   entries->pixmap   = NULL;
  390.  
  391.   /*  Open the requested file  */
  392.   if (! (fp = fopen (filename, "r")))
  393.     {
  394.       palette_entries_free (entries);
  395.       g_warning ("Failed to open palette file %s: can't happen?", filename);
  396.       return;
  397.     }
  398.  
  399.   linenum = 0;
  400.  
  401.   fread (str, 13, 1, fp);
  402.   str[13] = '\0';
  403.   linenum++;
  404.   if (strcmp (str, "GIMP Palette\n"))
  405.     {
  406.       /* bad magic, but maybe it has \r\n at the end of lines? */
  407.       if (!strcmp (str, "GIMP Palette\r"))
  408.     g_message (_("Loading palette %s:\n"
  409.              "Corrupt palette:\n"
  410.              "missing magic header\n"
  411.              "Does this file need converting from DOS?"), filename);
  412.       else
  413.     g_message (_("Loading palette %s:\n"
  414.              "Corrupt palette: missing magic header"), filename);
  415.       fclose (fp);
  416.       palette_entries_free (entries);
  417.       return;
  418.     }
  419.  
  420.   while (!feof (fp))
  421.     {
  422.       if (!fgets (str, 512, fp))
  423.     {
  424.       if (feof (fp))
  425.         break;
  426.       g_message (_("Loading palette %s (line %d):\nRead error"),
  427.              filename, linenum);
  428.       fclose (fp);
  429.       palette_entries_free (entries);
  430.       return;
  431.     }
  432.  
  433.       linenum++;
  434.  
  435.       if (str[0] != '#')
  436.     {
  437.       tok = strtok (str, " \t");
  438.       if (tok)
  439.         r = atoi (tok);
  440.       else
  441.         /* maybe we should just abort? */
  442.         g_message (_("Loading palette %s (line %d):\n"
  443.              "Missing RED component"), filename, linenum);
  444.  
  445.       tok = strtok (NULL, " \t");
  446.       if (tok)
  447.         g = atoi (tok);
  448.       else
  449.         g_message (_("Loading palette %s (line %d):\n"
  450.              "Missing GREEN component"), filename, linenum);
  451.       
  452.       tok = strtok (NULL, " \t");
  453.       if (tok)
  454.         b = atoi (tok);
  455.       else
  456.         g_message (_("Loading palette %s (line %d):\n"
  457.              "Missing BLUE component"), filename, linenum);
  458.  
  459.       /* optional name */
  460.       tok = strtok (NULL, "\n");
  461.  
  462.       if (r < 0 || r > 255 ||
  463.           g < 0 || g > 255 ||
  464.           b < 0 || b > 255)
  465.         g_message (_("Loading palette %s (line %d):\n"
  466.              "RGB value out of range"), filename, linenum);
  467.  
  468.       palette_entries_add_entry (entries, tok, r, g, b);
  469.     }
  470.     }
  471.  
  472.   /*  Clean up  */
  473.   fclose (fp);
  474.   entries->changed = FALSE;
  475.  
  476.   palette_entries_list_insert (entries);
  477.  
  478.   /*  Check if the current palette is the default one  */
  479.   if (strcmp (default_palette, g_basename (filename)) == 0)
  480.     default_palette_entries = entries;
  481. }
  482.  
  483. static void
  484. palette_entry_free (PaletteEntry *entry)
  485. {
  486.   if (entry->name)
  487.     g_free (entry->name);
  488.  
  489.   g_free (entry);
  490. }
  491.  
  492. static void
  493. palette_entries_delete (gchar *filename)
  494. {
  495.   if (filename)
  496.     unlink (filename);
  497. }
  498.  
  499. static void
  500. palette_entries_save (PaletteEntries *palette,
  501.               gchar          *filename)
  502. {
  503.   PaletteEntry *entry;
  504.   GSList *list;
  505.   FILE *fp;
  506.  
  507.   if (! filename)
  508.     return;
  509.  
  510.   /*  Open the requested file  */
  511.   if (! (fp = fopen (filename, "w")))
  512.     {
  513.       g_message (_("Can't save palette \"%s\"\n"), filename);
  514.       return;
  515.     }
  516.  
  517.   fprintf (fp, "GIMP Palette\n");
  518.   fprintf (fp, "# %s -- GIMP Palette file\n", palette->name);
  519.  
  520.   for (list = palette->colors; list; list = g_slist_next (list))
  521.     {
  522.       entry = (PaletteEntry *) list->data;
  523.  
  524.       fprintf (fp, "%d %d %d\t%s\n",
  525.            entry->color[0], entry->color[1], entry->color[2], entry->name);
  526.     }
  527.  
  528.   /*  Clean up  */
  529.   fclose (fp);
  530. }
  531.  
  532. static void
  533. palette_save_palettes (void)
  534. {
  535.   PaletteEntries *entries;
  536.   GSList *list;
  537.  
  538.   for (list = palette_entries_list; list; list = g_slist_next (list))
  539.     {
  540.       entries = (PaletteEntries *) list->data;
  541.  
  542.       /*  If the palette has been changed, save it, if possible  */
  543.       if (entries->changed)
  544.     /*  save the palette  */
  545.     palette_entries_save (entries, entries->filename);
  546.     }
  547. }
  548.  
  549. static void 
  550. palette_entries_update_small_preview (PaletteEntries *entries,
  551.                       GdkGC          *gc)
  552. {
  553.   guchar rgb_buf[SM_PREVIEW_WIDTH * SM_PREVIEW_HEIGHT * 3];
  554.   GSList *list;
  555.   gint index;
  556.   PaletteEntry *entry;
  557.  
  558.   memset (rgb_buf, 0x0, sizeof (rgb_buf));
  559.  
  560.   gdk_draw_rgb_image (entries->pixmap,
  561.               gc,
  562.               0,
  563.               0,
  564.               SM_PREVIEW_WIDTH,
  565.               SM_PREVIEW_HEIGHT,
  566.               GDK_RGB_DITHER_NORMAL,
  567.               rgb_buf,
  568.               SM_PREVIEW_WIDTH*3);
  569.  
  570.   index = 0;
  571.   for (list = entries->colors; list; list = g_slist_next (list))
  572.     {
  573.       guchar cell[3*3*3];
  574.       gint loop;
  575.  
  576.       entry = list->data;
  577.  
  578.       for (loop = 0; loop < 27 ; loop+=3)
  579.     {
  580.       cell[0+loop] = entry->color[0];
  581.       cell[1+loop] = entry->color[1];
  582.       cell[2+loop] = entry->color[2];
  583.     }
  584.  
  585.       gdk_draw_rgb_image (entries->pixmap,
  586.               gc,
  587.               1 + (index % ((SM_PREVIEW_WIDTH-2) / 3)) * 3,
  588.               1 + (index / ((SM_PREVIEW_WIDTH-2) / 3)) * 3,
  589.               3,
  590.               3,
  591.               GDK_RGB_DITHER_NORMAL,
  592.               cell,
  593.               3);
  594.  
  595.       index++;
  596.  
  597.       if (index >= (((SM_PREVIEW_WIDTH-2) * (SM_PREVIEW_HEIGHT-2)) / 9))
  598.     break;
  599.     }
  600. }
  601.  
  602. static void
  603. palette_entries_list_insert (PaletteEntries *entries)
  604. {
  605.   PaletteEntries *p_entries;
  606.   GSList *list;
  607.   gint    pos = 0;
  608.  
  609.   for (list = palette_entries_list; list; list = g_slist_next (list))
  610.     {
  611.       p_entries = (PaletteEntries *) list->data;
  612.       
  613.       /*  to make sure we get something!  */
  614.       if (p_entries == NULL)
  615.     p_entries = default_palette_entries;
  616.  
  617.       if (strcmp (p_entries->name, entries->name) > 0)
  618.     break;
  619.  
  620.       pos++;
  621.     }
  622.  
  623.   /*  add it to the list  */
  624.   num_palette_entries++;
  625.   palette_entries_list = g_slist_insert (palette_entries_list,
  626.                      (gpointer) entries, pos);
  627. }
  628.  
  629. /*  general palette clist update functions  **********************************/
  630.  
  631. void
  632. palette_clist_init (GtkWidget *clist, 
  633.             GtkWidget *shell,
  634.             GdkGC     *gc)
  635. {
  636.   PaletteEntries *p_entries = NULL;
  637.   GSList *list;
  638.   gint pos;
  639.  
  640.   pos = 0;
  641.   for (list = palette_entries_list; list; list = g_slist_next (list))
  642.     {
  643.       p_entries = (PaletteEntries *) list->data;
  644.  
  645.       /*  to make sure we get something!  */
  646.       if (p_entries == NULL)
  647.     p_entries = default_palette_entries;
  648.  
  649.       palette_clist_insert (clist, shell, gc, p_entries, pos);
  650.  
  651.       pos++;
  652.     }
  653. }
  654.  
  655. void
  656. palette_clist_insert (GtkWidget      *clist, 
  657.               GtkWidget      *shell,
  658.               GdkGC          *gc,
  659.               PaletteEntries *entries,
  660.               gint            pos)
  661. {
  662.   gchar *string[3];
  663.  
  664.   string[0] = NULL;
  665.   string[1] = g_strdup_printf ("%d", entries->n_colors);
  666.   string[2] = entries->name;
  667.  
  668.   gtk_clist_insert (GTK_CLIST (clist), pos, string);
  669.  
  670.   g_free (string[1]);
  671.  
  672.   if (entries->pixmap == NULL)
  673.     {
  674.       entries->pixmap = gdk_pixmap_new (shell->window,
  675.                     SM_PREVIEW_WIDTH, 
  676.                     SM_PREVIEW_HEIGHT, 
  677.                     gtk_widget_get_visual (shell)->depth);
  678.       palette_entries_update_small_preview (entries, gc);
  679.     }
  680.  
  681.   gtk_clist_set_pixmap (GTK_CLIST (clist), pos, 0, entries->pixmap, NULL);
  682.   gtk_clist_set_row_data (GTK_CLIST (clist), pos, (gpointer) entries);
  683. }  
  684.  
  685. /*  palette dialog clist update functions  ***********************************/
  686.  
  687. static void
  688. palette_dialog_clist_insert (PaletteDialog  *palette,
  689.                  PaletteEntries *entries)
  690. {
  691.   PaletteEntries *chk_entries;
  692.   GSList *list;
  693.   gint pos;
  694.  
  695.   pos = 0;
  696.   for (list = palette_entries_list; list; list = g_slist_next (list))
  697.     {
  698.       chk_entries = (PaletteEntries *) list->data;
  699.       
  700.       /*  to make sure we get something!  */
  701.       if (chk_entries == NULL)
  702.     return;
  703.  
  704.       if (strcmp (entries->name, chk_entries->name) == 0)
  705.     break;
  706.  
  707.       pos++;
  708.     }
  709.  
  710.   gtk_clist_freeze (GTK_CLIST (palette->clist));
  711.   palette_clist_insert (palette->clist, palette->shell, palette->gc,
  712.             entries, pos);
  713.   gtk_clist_thaw (GTK_CLIST (palette->clist));
  714. }
  715.  
  716. static void
  717. palette_dialog_clist_set_text (PaletteDialog  *palette,
  718.                    PaletteEntries *entries)
  719. {
  720.   PaletteEntries *chk_entries = NULL;
  721.   GSList *list;
  722.   gchar *num_buf;
  723.   gint pos;
  724.  
  725.   pos = 0;
  726.   for (list = palette_entries_list; list; list = g_slist_next (list))
  727.     {
  728.       chk_entries = (PaletteEntries *) list->data;
  729.       
  730.       if (entries == chk_entries)
  731.     break;
  732.  
  733.       pos++;
  734.     }
  735.  
  736.   if (chk_entries == NULL)
  737.     return; /* This is actually and error */
  738.  
  739.   num_buf = g_strdup_printf ("%d", entries->n_colors);;
  740.  
  741.   gtk_clist_set_text (GTK_CLIST (palette->clist), pos, 1, num_buf);
  742.  
  743.   g_free (num_buf);
  744. }
  745.  
  746. static void
  747. palette_dialog_clist_refresh (PaletteDialog *palette)
  748. {
  749.   gtk_clist_freeze (GTK_CLIST (palette->clist));
  750.   gtk_clist_clear (GTK_CLIST (palette->clist));
  751.   palette_clist_init (palette->clist, palette->shell, palette->gc);
  752.   gtk_clist_thaw (GTK_CLIST (palette->clist));
  753.  
  754.   palette->entries = palette_entries_list->data;
  755. }
  756.  
  757. static void 
  758. palette_dialog_clist_scroll_to_current (PaletteDialog *palette)
  759. {
  760.   PaletteEntries *p_entries;
  761.   GSList *list;
  762.   gint pos;
  763.  
  764.   if (palette && palette->entries)
  765.     {
  766.       pos = 0;
  767.       for (list = palette_entries_list; list; list = g_slist_next (list))
  768.     {
  769.       p_entries = (PaletteEntries *) list->data;
  770.       
  771.       if (p_entries == palette->entries)
  772.         break;
  773.  
  774.       pos++;
  775.     }
  776.  
  777.       gtk_clist_unselect_all (GTK_CLIST (palette->clist));
  778.       gtk_clist_select_row (GTK_CLIST (palette->clist), pos, -1);
  779.       gtk_clist_moveto (GTK_CLIST (palette->clist), pos, 0, 0.0, 0.0); 
  780.     }
  781. }
  782.  
  783. /*  update functions for all palette dialogs  ********************************/
  784.  
  785. static void
  786. palette_insert_all (PaletteEntries *entries)
  787. {
  788.   PaletteDialog *palette;
  789.  
  790.   if ((palette = top_level_palette))
  791.     {
  792.       palette_dialog_clist_insert (palette, entries);
  793.  
  794.       if (palette->entries == NULL)
  795.     {
  796.       palette->entries = entries;
  797.       palette_dialog_redraw (palette);
  798.     }
  799.     }
  800.  
  801.   if ((palette = top_level_edit_palette))
  802.     {
  803.       palette_dialog_clist_insert (palette, entries);
  804.  
  805.       palette->entries = entries;
  806.       palette_dialog_redraw (palette);
  807.  
  808.       palette_dialog_clist_scroll_to_current (palette);
  809.     }
  810.  
  811.   /*  Update other selectors on screen  */
  812.   palette_select_clist_insert_all (entries);
  813. }
  814.  
  815. static void
  816. palette_update_all (PaletteEntries *entries)
  817. {
  818.   PaletteDialog *palette;
  819.   GdkGC *gc = NULL;
  820.  
  821.   if (top_level_palette)
  822.     gc = top_level_palette->gc;
  823.   else if (top_level_edit_palette)
  824.     gc = top_level_edit_palette->gc;
  825.  
  826.   if (gc)
  827.     palette_entries_update_small_preview (entries, gc);
  828.  
  829.   if ((palette = top_level_palette))
  830.     {
  831.       if (palette->entries == entries)
  832.     {
  833.       palette->columns_valid = FALSE;
  834.       palette_dialog_redraw (palette);
  835.     }
  836.       palette_dialog_clist_set_text (palette, entries);
  837.     }
  838.  
  839.   if ((palette = top_level_edit_palette))
  840.     {
  841.       if (palette->entries == entries)
  842.     {
  843.       palette->columns_valid = FALSE;
  844.       palette_dialog_redraw (palette);
  845.       palette_dialog_clist_scroll_to_current (palette);
  846.     }
  847.       palette_dialog_clist_set_text (palette, entries);
  848.     }
  849.  
  850.   /*  Update other selectors on screen  */
  851.   palette_select_set_text_all (entries);
  852. }
  853.  
  854. static void
  855. palette_draw_all (PaletteEntries *entries,
  856.           PaletteEntry   *color)
  857. {
  858.   PaletteDialog *palette;
  859.   GdkGC *gc = NULL;
  860.  
  861.   if (top_level_palette)
  862.     gc = top_level_palette->gc;
  863.   else if (top_level_edit_palette)
  864.     gc = top_level_edit_palette->gc;
  865.  
  866.   if (gc)
  867.     palette_entries_update_small_preview (entries, gc);
  868.  
  869.   if ((palette = top_level_palette))
  870.     {
  871.       if (palette->entries == entries)
  872.     {
  873.       palette_dialog_draw_entries (palette,
  874.                        color->position / palette->columns,
  875.                        color->position % palette->columns);
  876.     }
  877.     }
  878.  
  879.   if ((palette = top_level_edit_palette))
  880.     {
  881.       if (palette->entries == entries)
  882.     {
  883.       palette_dialog_draw_entries (palette,
  884.                        color->position / palette->columns,
  885.                        color->position % palette->columns);
  886.     }
  887.     }
  888. }
  889.  
  890. static void
  891. palette_refresh_all (void)
  892. {
  893.   PaletteDialog *palette;
  894.  
  895.   default_palette_entries = NULL;
  896.  
  897.   palettes_free ();
  898.   palettes_init (FALSE);
  899.  
  900.   if ((palette = top_level_palette))
  901.     {
  902.       palette_dialog_clist_refresh (palette);
  903.       palette->columns_valid = FALSE;
  904.       palette_dialog_redraw (palette);
  905.       palette_dialog_clist_scroll_to_current (palette);
  906.     }
  907.  
  908.   if ((palette = top_level_edit_palette))
  909.     {
  910.       palette_dialog_clist_refresh (palette);
  911.       palette->columns_valid = FALSE;
  912.       palette_dialog_redraw (palette);
  913.       palette_dialog_clist_scroll_to_current (palette);
  914.     }
  915.  
  916.   /*  Update other selectors on screen  */
  917.   palette_select_refresh_all ();
  918. }
  919.  
  920. /*  called from color_picker.h  *********************************************/
  921.  
  922. void
  923. palette_set_active_color (gint r,
  924.               gint g,
  925.               gint b,
  926.               gint state)
  927. {
  928.   if (top_level_edit_palette && top_level_edit_palette->entries) 
  929.     {
  930.       switch (state) 
  931.      { 
  932.      case COLOR_NEW: 
  933.       top_level_edit_palette->color =
  934.         palette_entries_add_entry (top_level_edit_palette->entries,
  935.                        _("Untitled"), r, g, b); 
  936.       palette_update_all (top_level_edit_palette->entries);
  937.        break;
  938.  
  939.      case COLOR_UPDATE_NEW: 
  940.        top_level_edit_palette->color->color[0] = r;
  941.        top_level_edit_palette->color->color[1] = g;
  942.        top_level_edit_palette->color->color[2] = b;
  943.       palette_draw_all (top_level_edit_palette->entries,
  944.                 top_level_edit_palette->color);
  945.        break; 
  946.       
  947.      default: 
  948.        break; 
  949.      } 
  950.     } 
  951.   
  952.   if (active_color == FOREGROUND)
  953.     gimp_context_set_foreground (gimp_context_get_user (), r, g, b);
  954.   else if (active_color == BACKGROUND)
  955.     gimp_context_set_background (gimp_context_get_user (), r, g, b);
  956. }
  957.  
  958. /*  called from palette_select.c  ********************************************/
  959.  
  960. void 
  961. palette_select_palette_init (void)
  962. {
  963.   if (top_level_edit_palette == NULL)
  964.     {
  965.       top_level_edit_palette = palette_dialog_new (FALSE);
  966.       dialog_register (top_level_edit_palette->shell);
  967.     }
  968. }
  969.  
  970. void 
  971. palette_create_edit (PaletteEntries *entries)
  972. {
  973.   if (top_level_edit_palette == NULL)
  974.     {
  975.       top_level_edit_palette = palette_dialog_new (FALSE);
  976.       dialog_register (top_level_edit_palette->shell);
  977.  
  978.       gtk_widget_show (top_level_edit_palette->shell);
  979.       palette_dialog_draw_entries (top_level_edit_palette, -1, -1);
  980.     }
  981.   else
  982.     {
  983.       if (! GTK_WIDGET_VISIBLE (top_level_edit_palette->shell))
  984.     {
  985.       gtk_widget_show (top_level_edit_palette->shell);
  986.       palette_dialog_draw_entries (top_level_edit_palette, -1, -1);
  987.     }
  988.       else
  989.     {
  990.       gdk_window_raise (top_level_edit_palette->shell->window);
  991.     }
  992.     }
  993.  
  994.   if (entries != NULL)
  995.     {
  996.       top_level_edit_palette->entries = entries;
  997.       palette_dialog_clist_scroll_to_current (top_level_edit_palette);
  998.     }
  999. }
  1000.  
  1001. static void
  1002. palette_select_callback (gint                r,
  1003.              gint                g,
  1004.              gint                b,
  1005.              ColorNotebookState  state,
  1006.              void               *data)
  1007. {
  1008.   PaletteDialog *palette;
  1009.   guchar *color;
  1010.   
  1011.   palette = data;
  1012.  
  1013.   if (palette && palette->entries)
  1014.     {
  1015.       switch (state)
  1016.     {
  1017.     case COLOR_NOTEBOOK_UPDATE:
  1018.       break;
  1019.  
  1020.     case COLOR_NOTEBOOK_OK:
  1021.       if (palette->color)
  1022.         {
  1023.           color = palette->color->color;
  1024.  
  1025.           color[0] = r;
  1026.           color[1] = g;
  1027.           color[2] = b;
  1028.  
  1029.           /*  Update either foreground or background colors  */
  1030.           if (active_color == FOREGROUND)
  1031.         gimp_context_set_foreground (gimp_context_get_user (), r, g, b);
  1032.           else if (active_color == BACKGROUND)
  1033.         gimp_context_set_background (gimp_context_get_user (), r, g, b);
  1034.  
  1035.           palette_draw_all (palette->entries, palette->color);
  1036.         }
  1037.  
  1038.       /* Fallthrough */
  1039.     case COLOR_NOTEBOOK_CANCEL:
  1040.       if (palette->color_notebook_active)
  1041.         {
  1042.           color_notebook_hide (palette->color_notebook);
  1043.           palette->color_notebook_active = FALSE;
  1044.         }
  1045.     }
  1046.     }
  1047. }
  1048.  
  1049. /*  the palette dialog popup menu & callbacks  *******************************/
  1050.  
  1051. static void
  1052. palette_dialog_new_entry_callback (GtkWidget *widget,
  1053.                    gpointer   data)
  1054. {
  1055.   PaletteDialog *palette;
  1056.  
  1057.   palette = data;
  1058.  
  1059.   if (palette && palette->entries)
  1060.     {
  1061.       guchar col[3];
  1062.  
  1063.       if (active_color == FOREGROUND)
  1064.     gimp_context_get_foreground (gimp_context_get_user (),
  1065.                      &col[0], &col[1], &col[2]);
  1066.       else if (active_color == BACKGROUND)
  1067.     gimp_context_get_background (gimp_context_get_user (),
  1068.                      &col[0], &col[1], &col[2]);
  1069.  
  1070.       palette->color = palette_entries_add_entry (palette->entries,
  1071.                           _("Untitled"),
  1072.                           col[0], col[1], col[2]);
  1073.  
  1074.       palette_update_all (palette->entries);
  1075.     }
  1076. }
  1077.  
  1078. static void
  1079. palette_dialog_edit_entry_callback (GtkWidget *widget,
  1080.                     gpointer   data)
  1081. {
  1082.   PaletteDialog *palette;
  1083.   guchar *color;
  1084.  
  1085.   palette = data;
  1086.   if (palette && palette->entries && palette->color)
  1087.     {
  1088.       color = palette->color->color;
  1089.  
  1090.       if (!palette->color_notebook)
  1091.     {
  1092.       palette->color_notebook =
  1093.         color_notebook_new (color[0], color[1], color[2],
  1094.                 palette_select_callback, palette,
  1095.                 FALSE);
  1096.       palette->color_notebook_active = TRUE;
  1097.     }
  1098.       else
  1099.     {
  1100.       if (!palette->color_notebook_active)
  1101.         {
  1102.           color_notebook_show (palette->color_notebook);
  1103.           palette->color_notebook_active = TRUE;
  1104.         }
  1105.  
  1106.       color_notebook_set_color (palette->color_notebook,
  1107.                     color[0], color[1], color[2], 1);
  1108.     }
  1109.     }
  1110. }
  1111.  
  1112. static void
  1113. palette_dialog_delete_entry_callback (GtkWidget *widget,
  1114.                       gpointer   data)
  1115. {
  1116.   PaletteEntry *entry;
  1117.   PaletteDialog *palette;
  1118.   GSList *tmp_link;
  1119.   gint pos = 0;
  1120.  
  1121.   palette = data;
  1122.  
  1123.   if (palette && palette->entries && palette->color)
  1124.     {
  1125.       entry = palette->color;
  1126.       palette->entries->colors = g_slist_remove (palette->entries->colors, entry);
  1127.       palette->entries->n_colors--;
  1128.       palette->entries->changed = TRUE;
  1129.  
  1130.       pos = entry->position;
  1131.       palette_entry_free (entry);
  1132.  
  1133.       tmp_link = g_slist_nth (palette->entries->colors, pos);
  1134.  
  1135.       if (tmp_link)
  1136.     {
  1137.       palette->color = tmp_link->data;
  1138.  
  1139.       while (tmp_link)
  1140.         {
  1141.           entry = tmp_link->data;
  1142.           tmp_link = tmp_link->next;
  1143.           entry->position = pos++;
  1144.         }
  1145.     }
  1146.       else
  1147.     {
  1148.       tmp_link = g_slist_nth (palette->entries->colors, pos - 1);
  1149.       if (tmp_link)
  1150.         palette->color = tmp_link->data;
  1151.     }
  1152.  
  1153.       if (palette->entries->n_colors == 0)
  1154.     palette->color =
  1155.       palette_entries_add_entry (palette->entries,
  1156.                      _("Black"), 0, 0, 0);
  1157.  
  1158.       palette_update_all (palette->entries);
  1159.     }
  1160. }
  1161.  
  1162. static void
  1163. palette_dialog_create_popup_menu (PaletteDialog *palette)
  1164. {
  1165.   GtkWidget *menu;
  1166.   GtkWidget *menu_item;
  1167.  
  1168.   palette->popup_menu = menu = gtk_menu_new ();
  1169.  
  1170.   menu_item = gtk_menu_item_new_with_label (_("New"));
  1171.   gtk_menu_append (GTK_MENU (menu), menu_item);
  1172.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
  1173.               GTK_SIGNAL_FUNC (palette_dialog_new_entry_callback),
  1174.               (gpointer) palette);
  1175.   gtk_widget_show (menu_item);
  1176.  
  1177.   menu_item = gtk_menu_item_new_with_label (_("Edit"));
  1178.   gtk_menu_append (GTK_MENU (menu), menu_item);
  1179.  
  1180.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
  1181.               GTK_SIGNAL_FUNC (palette_dialog_edit_entry_callback),
  1182.               (gpointer) palette);
  1183.   gtk_widget_show (menu_item);
  1184.  
  1185.   palette->edit_menu_item = menu_item;
  1186.  
  1187.   menu_item = gtk_menu_item_new_with_label (_("Delete"));
  1188.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
  1189.               GTK_SIGNAL_FUNC (palette_dialog_delete_entry_callback),
  1190.               (gpointer) palette);
  1191.   gtk_menu_append (GTK_MENU (menu), menu_item);
  1192.   gtk_widget_show (menu_item);
  1193.  
  1194.   palette->delete_menu_item = menu_item;
  1195. }
  1196.  
  1197. /*  the color area event callbacks  ******************************************/
  1198.  
  1199. static gint
  1200. palette_dialog_eventbox_button_press (GtkWidget      *widget,
  1201.                       GdkEventButton *bevent,
  1202.                       PaletteDialog  *palette)
  1203. {
  1204.   if (gtk_get_event_widget ((GdkEvent *) bevent) == palette->color_area)
  1205.     return FALSE;
  1206.  
  1207.   if (bevent->button == 3)
  1208.     {
  1209.       if (GTK_WIDGET_SENSITIVE (palette->edit_menu_item))
  1210.     {
  1211.       gtk_widget_set_sensitive (palette->edit_menu_item, FALSE);
  1212.       gtk_widget_set_sensitive (palette->delete_menu_item, FALSE);
  1213.     }
  1214.  
  1215.       gtk_menu_popup (GTK_MENU (palette->popup_menu), NULL, NULL, 
  1216.               NULL, NULL, 3,
  1217.               bevent->time);
  1218.     }
  1219.  
  1220.   return TRUE;
  1221. }
  1222.  
  1223. static gint
  1224. palette_dialog_color_area_events (GtkWidget     *widget,
  1225.                   GdkEvent      *event,
  1226.                   PaletteDialog *palette)
  1227. {
  1228.   GdkEventButton *bevent;
  1229.   GSList *tmp_link;
  1230.   gint r, g, b;
  1231.   gint entry_width;
  1232.   gint entry_height;
  1233.   gint row, col;
  1234.   gint pos;
  1235.  
  1236.   switch (event->type)
  1237.     {
  1238.     case GDK_EXPOSE:
  1239.       palette_dialog_redraw (palette);
  1240.       break;
  1241.  
  1242.     case GDK_BUTTON_PRESS:
  1243.       bevent = (GdkEventButton *) event;
  1244.       entry_width  = palette->col_width + SPACING;
  1245.       entry_height = (ENTRY_HEIGHT * palette->zoom_factor) +  SPACING;
  1246.       col = (bevent->x - 1) / entry_width;
  1247.       row = (bevent->y - 1) / entry_height;
  1248.       pos = row * palette->columns + col;
  1249.       
  1250.       tmp_link = (palette->entries != NULL) ? g_slist_nth (palette->entries->colors, pos) : NULL;
  1251.  
  1252.       if (tmp_link)
  1253.     palette->dnd_color = tmp_link->data;
  1254.       else
  1255.     palette->dnd_color = NULL;
  1256.  
  1257.       if ((bevent->button == 1 || bevent->button == 3) && palette->entries)
  1258.     {
  1259.       if (tmp_link)
  1260.         {
  1261.           if (palette->color)
  1262.         {
  1263.           palette->freeze_update = TRUE;
  1264.            palette_dialog_draw_entries (palette, -1, -1);
  1265.           palette->freeze_update = FALSE;
  1266.         }
  1267.           palette->color = tmp_link->data;
  1268.  
  1269.           /*  Update either foreground or background colors  */
  1270.           r = palette->color->color[0];
  1271.           g = palette->color->color[1];
  1272.           b = palette->color->color[2];
  1273.           if (active_color == FOREGROUND)
  1274.         {
  1275.           if (bevent->state & GDK_CONTROL_MASK)
  1276.             gimp_context_set_background (gimp_context_get_user (),
  1277.                          r, g, b);
  1278.           else
  1279.             gimp_context_set_foreground (gimp_context_get_user (),
  1280.                          r, g, b);
  1281.         }
  1282.           else if (active_color == BACKGROUND)
  1283.         {
  1284.           if (bevent->state & GDK_CONTROL_MASK)
  1285.             gimp_context_set_foreground (gimp_context_get_user (),
  1286.                          r, g, b);
  1287.           else
  1288.             gimp_context_set_background (gimp_context_get_user (),
  1289.                          r, g, b);
  1290.         }
  1291.  
  1292.           palette_dialog_draw_entries (palette, row, col);
  1293.           /*  Update the active color name  */
  1294.           gtk_entry_set_text (GTK_ENTRY (palette->color_name),
  1295.                   palette->color->name);
  1296.           gtk_widget_set_sensitive (palette->color_name, TRUE);
  1297.           /* palette_update_current_entry (palette); */
  1298.  
  1299.           if (bevent->button == 3)
  1300.         {
  1301.           if (! GTK_WIDGET_SENSITIVE (palette->edit_menu_item))
  1302.             {
  1303.               gtk_widget_set_sensitive (palette->edit_menu_item, TRUE);
  1304.               gtk_widget_set_sensitive (palette->delete_menu_item, TRUE);
  1305.             }
  1306.  
  1307.           gtk_menu_popup (GTK_MENU (palette->popup_menu), NULL, NULL, 
  1308.                   NULL, NULL, 3,
  1309.                   bevent->time);
  1310.         }
  1311.         }
  1312.       else
  1313.         {
  1314.           if (bevent->button == 3)
  1315.         {
  1316.           if (GTK_WIDGET_SENSITIVE (palette->edit_menu_item))
  1317.             {
  1318.               gtk_widget_set_sensitive (palette->edit_menu_item, FALSE);
  1319.               gtk_widget_set_sensitive (palette->delete_menu_item, FALSE);
  1320.             }
  1321.  
  1322.           gtk_menu_popup (GTK_MENU (palette->popup_menu), NULL, NULL, 
  1323.                   NULL, NULL, 3,
  1324.                   bevent->time);
  1325.         }
  1326.         }
  1327.     }
  1328.       break;
  1329.  
  1330.     default:
  1331.       break;
  1332.     }
  1333.  
  1334.   return FALSE;
  1335. }
  1336.  
  1337. /*  functions for drawing & updating the palette dialog color area  **********/
  1338.  
  1339. static int
  1340. palette_dialog_draw_color_row (guchar        **colors,
  1341.                    gint            ncolors,
  1342.                    gint            y,
  1343.                    gint            column_highlight,
  1344.                    guchar         *buffer,
  1345.                    PaletteDialog  *palette)
  1346. {
  1347.   guchar *p;
  1348.   guchar bcolor;
  1349.   gint width, height;
  1350.   gint entry_width;
  1351.   gint entry_height;
  1352.   gint vsize;
  1353.   gint vspacing;
  1354.   gint i, j;
  1355.   GtkWidget *preview;
  1356.  
  1357.   if (! palette)
  1358.     return -1;
  1359.  
  1360.   preview = palette->color_area;
  1361.  
  1362.   bcolor = 0;
  1363.  
  1364.   width = preview->requisition.width;
  1365.   height = preview->requisition.height;
  1366.   entry_width = palette->col_width;
  1367.   entry_height = (ENTRY_HEIGHT * palette->zoom_factor);
  1368.  
  1369.   if ((y >= 0) && ((y + SPACING) < height))
  1370.     vspacing = SPACING;
  1371.   else if (y < 0)
  1372.     vspacing = SPACING + y;
  1373.   else
  1374.     vspacing = height - y;
  1375.  
  1376.   if (vspacing > 0)
  1377.     {
  1378.       if (y < 0)
  1379.     y += SPACING - vspacing;
  1380.  
  1381.       for (i = SPACING - vspacing; i < SPACING; i++, y++)
  1382.     {
  1383.       p = buffer;
  1384.       for (j = 0; j < width; j++)
  1385.         {
  1386.           *p++ = bcolor;
  1387.           *p++ = bcolor;
  1388.           *p++ = bcolor;
  1389.         }
  1390.       
  1391.       if (column_highlight >= 0)
  1392.         {
  1393.           guchar *ph = &buffer[3*column_highlight*(entry_width+SPACING)];
  1394.           for (j = 0 ; j <= entry_width + SPACING; j++)
  1395.         {
  1396.           *ph++ = ~bcolor;
  1397.           *ph++ = ~bcolor;
  1398.           *ph++ = ~bcolor;
  1399.         }
  1400.            gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0,
  1401.                     y + entry_height + 1, width); 
  1402.         }
  1403.  
  1404.       gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, y, width);
  1405.     }
  1406.  
  1407.       if (y > SPACING)
  1408.     y += SPACING - vspacing;
  1409.     }
  1410.   else
  1411.     y += SPACING;
  1412.  
  1413.   vsize = (y >= 0) ? (entry_height) : (entry_height + y);
  1414.  
  1415.   if ((y >= 0) && ((y + entry_height) < height))
  1416.     vsize = entry_height;
  1417.   else if (y < 0)
  1418.     vsize = entry_height + y;
  1419.   else
  1420.     vsize = height - y;
  1421.  
  1422.   if (vsize > 0)
  1423.     {
  1424.       p = buffer;
  1425.       for (i = 0; i < ncolors; i++)
  1426.     {
  1427.       for (j = 0; j < SPACING; j++)
  1428.         {
  1429.           *p++ = bcolor;
  1430.           *p++ = bcolor;
  1431.           *p++ = bcolor;
  1432.         }
  1433.  
  1434.       for (j = 0; j < entry_width; j++)
  1435.         {
  1436.           *p++ = colors[i][0];
  1437.           *p++ = colors[i][1];
  1438.           *p++ = colors[i][2];
  1439.         }
  1440.     }
  1441.  
  1442.       for (i = 0; i < (palette->columns - ncolors); i++)
  1443.     {
  1444.       for (j = 0; j < (SPACING + entry_width); j++)
  1445.         {
  1446.           *p++ = 0;
  1447.           *p++ = 0;
  1448.           *p++ = 0;
  1449.         }
  1450.     }
  1451.  
  1452.       for (j = 0; j < SPACING; j++)
  1453.     {
  1454.       if (ncolors == column_highlight)
  1455.         {
  1456.           *p++ = ~bcolor;
  1457.           *p++ = ~bcolor;
  1458.           *p++ = ~bcolor;
  1459.         }
  1460.       else
  1461.         {
  1462.           *p++ = bcolor;
  1463.           *p++ = bcolor;
  1464.           *p++ = bcolor;
  1465.         }
  1466.     }
  1467.  
  1468.       if (y < 0)
  1469.     y += entry_height - vsize;
  1470.       for (i = 0; i < vsize; i++, y++)
  1471.     {
  1472.       if (column_highlight >= 0)
  1473.         {
  1474.           guchar *ph = &buffer[3*column_highlight*(entry_width+SPACING)];
  1475.           *ph++ = ~bcolor;
  1476.           *ph++ = ~bcolor;
  1477.           *ph++ = ~bcolor;
  1478.           ph += 3*(entry_width);
  1479.           *ph++ = ~bcolor;
  1480.           *ph++ = ~bcolor;
  1481.           *ph++ = ~bcolor;
  1482.         }
  1483.       gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, y, width);
  1484.     }
  1485.       if (y > entry_height)
  1486.     y += entry_height - vsize;
  1487.     }
  1488.   else
  1489.     y += entry_height;
  1490.  
  1491.   return y;
  1492. }
  1493.  
  1494. static void
  1495. palette_dialog_draw_entries (PaletteDialog *palette,
  1496.                  gint           row_start,
  1497.                  gint           column_highlight)
  1498. {
  1499.   PaletteEntry *entry;
  1500.   guchar *buffer;
  1501.   guchar **colors;
  1502.   GSList *tmp_link;
  1503.   gint width, height;
  1504.   gint entry_width;
  1505.   gint entry_height;
  1506.   gint index, y;
  1507.  
  1508.   if (palette && palette->entries)
  1509.     {
  1510.       width  = palette->color_area->requisition.width;
  1511.       height = palette->color_area->requisition.height;
  1512.  
  1513.       entry_width  = palette->col_width;
  1514.       entry_height = (ENTRY_HEIGHT * palette->zoom_factor);
  1515.  
  1516.       if (entry_width <= 0) return;
  1517.  
  1518.       colors = g_malloc (sizeof (guchar *) * palette->columns * 3);
  1519.       buffer = g_malloc (width * 3);
  1520.  
  1521.       if (row_start < 0)
  1522.     {
  1523.       y = 0;
  1524.       tmp_link = palette->entries->colors;
  1525.       column_highlight = -1;
  1526.     }
  1527.       else
  1528.     {
  1529.       y = (entry_height + SPACING) * row_start;
  1530.       tmp_link = g_slist_nth (palette->entries->colors,
  1531.                   row_start * palette->columns);
  1532.     }
  1533.       index = 0;
  1534.  
  1535.       while (tmp_link)
  1536.     {
  1537.       entry = tmp_link->data;
  1538.       tmp_link = tmp_link->next;
  1539.  
  1540.       colors[index] = entry->color;
  1541.       index++;
  1542.  
  1543.       if (index == palette->columns)
  1544.         {
  1545.           index = 0;
  1546.           y = palette_dialog_draw_color_row (colors, palette->columns, y,
  1547.                          column_highlight, buffer,
  1548.                          palette);
  1549.           if (y >= height || row_start >= 0)
  1550.         {
  1551.           /* This row only */
  1552.           gtk_widget_draw (palette->color_area, NULL);
  1553.           g_free (buffer);
  1554.           g_free (colors);
  1555.           return;
  1556.         }
  1557.         }
  1558.     }
  1559.  
  1560.       while (y < height)
  1561.     {
  1562.       y = palette_dialog_draw_color_row (colors, index, y, column_highlight,
  1563.                          buffer, palette);
  1564.       index = 0;
  1565.           if (row_start >= 0)
  1566.         break;
  1567.     }
  1568.  
  1569.       g_free (buffer);
  1570.       g_free (colors);
  1571.  
  1572.       if (palette->freeze_update == FALSE)
  1573.     gtk_widget_draw (palette->color_area, NULL);
  1574.     }
  1575. }
  1576.  
  1577. static void
  1578. palette_dialog_scroll_top_left (PaletteDialog *palette)
  1579. {
  1580.   GtkAdjustment *hadj;
  1581.   GtkAdjustment *vadj;
  1582.  
  1583.   /*  scroll viewport to top left  */
  1584.   if (palette && palette->scrolled_window)
  1585.     {
  1586.       hadj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (palette->scrolled_window));
  1587.       vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (palette->scrolled_window));
  1588.  
  1589.       if (hadj)
  1590.     gtk_adjustment_set_value (hadj, 0.0);
  1591.       if (vadj)
  1592.     gtk_adjustment_set_value (vadj, 0.0);
  1593.     }
  1594. }
  1595.  
  1596. static void
  1597. palette_dialog_redraw (PaletteDialog *palette)
  1598. {
  1599.   GtkWidget *parent;
  1600.   gint vsize;
  1601.   gint nrows;
  1602.   gint n_entries;
  1603.   gint preview_width;
  1604.   guint width;
  1605.  
  1606.   if (!palette->entries)
  1607.     return;
  1608.  
  1609.   width = palette->color_area->parent->parent->parent->allocation.width;
  1610.  
  1611.   if ((palette->columns_valid) && palette->last_width == width)
  1612.     return;
  1613.  
  1614.   palette->last_width = width;
  1615.   palette->col_width = width / (palette->columns + 1) - SPACING;
  1616.   if (palette->col_width < 0) palette->col_width = 0;
  1617.   palette->columns_valid = TRUE;
  1618.  
  1619.   n_entries = palette->entries->n_colors;
  1620.   nrows = n_entries / palette->columns;
  1621.   if (n_entries % palette->columns)
  1622.     nrows += 1;
  1623.  
  1624.   vsize = nrows * (SPACING + (gint) (ENTRY_HEIGHT * palette->zoom_factor)) + SPACING;
  1625.  
  1626.   parent = palette->color_area->parent->parent;
  1627.   gtk_widget_ref (palette->color_area->parent);
  1628.   gtk_container_remove (GTK_CONTAINER (parent), palette->color_area->parent);
  1629.  
  1630.   preview_width = (palette->col_width + SPACING) * palette->columns + SPACING;
  1631.  
  1632.   gtk_preview_size (GTK_PREVIEW (palette->color_area), preview_width, vsize);
  1633.  
  1634.   gtk_container_add (GTK_CONTAINER (parent), palette->color_area->parent);
  1635.   gtk_widget_unref (palette->color_area->parent);
  1636.  
  1637.   palette_dialog_draw_entries (palette, -1, -1);
  1638. }
  1639.  
  1640. /*  the palette dialog clist "select_row" callback  **************************/
  1641.  
  1642. static void
  1643. palette_dialog_list_item_update (GtkWidget      *widget, 
  1644.                  gint            row,
  1645.                  gint            column,
  1646.                  GdkEventButton *event,
  1647.                  gpointer        data)
  1648. {
  1649.   PaletteDialog *palette;
  1650.   PaletteEntries *p_entries;
  1651.  
  1652.   palette = (PaletteDialog *) data;
  1653.  
  1654.   if (palette->color_notebook_active)
  1655.     {
  1656.       color_notebook_hide (palette->color_notebook);
  1657.       palette->color_notebook_active = FALSE;
  1658.     }
  1659.  
  1660.   if (palette->color_notebook)
  1661.     color_notebook_free (palette->color_notebook);
  1662.   palette->color_notebook = NULL;
  1663.  
  1664.   p_entries = 
  1665.     (PaletteEntries *) gtk_clist_get_row_data (GTK_CLIST (palette->clist), row);
  1666.  
  1667.   palette->entries = p_entries;
  1668.   palette->columns_valid = FALSE;
  1669.  
  1670.   palette_dialog_redraw (palette);
  1671.   palette_dialog_scroll_top_left (palette);
  1672.  
  1673.   /*  Stop errors in case no colors are selected  */ 
  1674.   gtk_signal_handler_block (GTK_OBJECT (palette->color_name),
  1675.                 palette->entry_sig_id);
  1676.   gtk_entry_set_text (GTK_ENTRY (palette->color_name), _("Undefined")); 
  1677.   gtk_widget_set_sensitive (palette->color_name, FALSE);
  1678.   gtk_signal_handler_unblock (GTK_OBJECT (palette->color_name),
  1679.                   palette->entry_sig_id);
  1680. }
  1681.  
  1682. /*  the color name entry callback  *******************************************/
  1683.  
  1684. static void
  1685. palette_dialog_color_name_entry_changed (GtkWidget *widget,
  1686.                      gpointer   data)
  1687. {
  1688.   PaletteDialog *palette;
  1689.  
  1690.   palette = data;
  1691.   g_return_if_fail (palette->entries != NULL);
  1692.  
  1693.   if (palette->color->name)
  1694.     g_free (palette->color->name);
  1695.   palette->color->name = 
  1696.     g_strdup (gtk_entry_get_text (GTK_ENTRY (palette->color_name)));
  1697.  
  1698.   palette->entries->changed = TRUE;
  1699. }
  1700.  
  1701. /*  palette zoom functions & callbacks  **************************************/
  1702.  
  1703. static void
  1704. palette_dialog_redraw_zoom (PaletteDialog *palette)
  1705. {
  1706.   if (palette->zoom_factor > 4.0)
  1707.     {
  1708.       palette->zoom_factor = 4.0;
  1709.     }
  1710.   else if (palette->zoom_factor < 0.1)
  1711.     {
  1712.       palette->zoom_factor = 0.1;
  1713.     }
  1714.   
  1715.   palette->columns = COLUMNS;
  1716.   palette->columns_valid = FALSE;
  1717.   palette_dialog_redraw (palette); 
  1718.  
  1719.   palette_dialog_scroll_top_left (palette);
  1720. }
  1721.  
  1722. static void
  1723. palette_dialog_zoomin_callback (GtkWidget *widget,
  1724.                 gpointer   data)
  1725. {
  1726.   PaletteDialog *palette = data;
  1727.  
  1728.   palette->zoom_factor += 0.1;
  1729.   palette_dialog_redraw_zoom (palette);
  1730. }
  1731.  
  1732. static void
  1733. palette_dialog_zoomout_callback (GtkWidget *widget,
  1734.                  gpointer   data)
  1735. {
  1736.   PaletteDialog *palette = data;
  1737.  
  1738.   palette->zoom_factor -= 0.1;
  1739.   palette_dialog_redraw_zoom (palette);
  1740. }
  1741.  
  1742. /*  the palette edit ops callbacks  ******************************************/
  1743.  
  1744. static void
  1745. palette_dialog_add_entries_callback (GtkWidget *widget,
  1746.                      gchar     *palette_name,
  1747.                      gpointer   data)
  1748. {
  1749.   PaletteEntries *entries;
  1750.  
  1751.   entries = palette_entries_new (palette_name);
  1752.  
  1753.   palette_insert_all (entries);
  1754. }
  1755.  
  1756. static void
  1757. palette_dialog_new_callback (GtkWidget *widget,
  1758.                  gpointer   data)
  1759. {
  1760.   GtkWidget *qbox;
  1761.  
  1762.   qbox = gimp_query_string_box (_("New Palette"),
  1763.                 gimp_standard_help_func,
  1764.                 "dialogs/palette_editor/new_palette.html",
  1765.                 _("Enter a name for new palette"),
  1766.                 NULL,
  1767.                 NULL, NULL,
  1768.                 palette_dialog_add_entries_callback, data);
  1769.   gtk_widget_show (qbox);
  1770. }
  1771.  
  1772. static void
  1773. palette_dialog_do_delete_callback (GtkWidget *widget,
  1774.                    gboolean   delete,
  1775.                    gpointer   data)
  1776. {
  1777.   PaletteDialog  *palette;
  1778.   PaletteEntries *entries;
  1779.  
  1780.   palette = (PaletteDialog *) data;
  1781.  
  1782.   gtk_widget_set_sensitive (palette->shell, TRUE);
  1783.  
  1784.   if (!delete)
  1785.     return;
  1786.  
  1787.   if (palette && palette->entries)
  1788.     {
  1789.       entries = palette->entries;
  1790.       if (entries && entries->filename)
  1791.     palette_entries_delete (entries->filename);
  1792.  
  1793.       palette_entries_list = g_slist_remove (palette_entries_list, entries);
  1794.  
  1795.       palette_refresh_all ();
  1796.     }
  1797. }
  1798.  
  1799. static void
  1800. palette_dialog_delete_callback (GtkWidget *widget,
  1801.                 gpointer   data)
  1802. {
  1803.   PaletteDialog *palette;
  1804.  
  1805.   GtkWidget *dialog;
  1806.   gchar     *str;
  1807.  
  1808.   palette = data;
  1809.  
  1810.   if (!palette || !palette->entries)
  1811.     return;
  1812.  
  1813.   gtk_widget_set_sensitive (palette->shell, FALSE);
  1814.  
  1815.   str = g_strdup_printf (_("Are you sure you want to delete\n"
  1816.                            "\"%s\" from the list and from disk?"),
  1817.                          palette->entries->name);
  1818.  
  1819.   dialog = gimp_query_boolean_box (_("Delete Palette"),
  1820.                    gimp_standard_help_func,
  1821.                    "dialogs/palette_editor/delete_palette.html",
  1822.                    FALSE,
  1823.                    str,
  1824.                    _("Delete"), _("Cancel"),
  1825.                    NULL, NULL,
  1826.                    palette_dialog_do_delete_callback,
  1827.                    palette);
  1828.  
  1829.   g_free (str);
  1830.  
  1831.   gtk_widget_show (dialog);
  1832. }
  1833.  
  1834. static void
  1835. palette_dialog_import_callback (GtkWidget *widget,
  1836.                 gpointer   data)
  1837. {
  1838.   if (!import_dialog)
  1839.     {
  1840.       import_dialog = palette_import_dialog_new ((PaletteDialog *) data);
  1841.       gtk_widget_show (import_dialog->dialog);
  1842.     }
  1843.   else
  1844.     {
  1845.       gdk_window_raise (import_dialog->dialog->window);
  1846.     }
  1847. }
  1848.  
  1849. static void
  1850. palette_dialog_merge_entries_callback (GtkWidget *widget,
  1851.                        gchar     *palette_name,
  1852.                        gpointer   data)
  1853. {
  1854.   PaletteDialog  *palette;
  1855.   PaletteEntries *p_entries;
  1856.   PaletteEntries *new_entries;
  1857.   GList          *sel_list;
  1858.  
  1859.   new_entries = palette_entries_new (palette_name);
  1860.  
  1861.   palette = (PaletteDialog *) data;
  1862.  
  1863.   sel_list = GTK_CLIST (palette->clist)->selection;
  1864.  
  1865.   while (sel_list)
  1866.     {
  1867.       gint    row;
  1868.       GSList *cols;
  1869.  
  1870.       row = GPOINTER_TO_INT (sel_list->data);
  1871.       p_entries = 
  1872.     (PaletteEntries *) gtk_clist_get_row_data (GTK_CLIST (palette->clist), row);
  1873.  
  1874.       /* Go through each palette and merge the colors */
  1875.       cols = p_entries->colors;
  1876.       while (cols)
  1877.     {
  1878.       PaletteEntry *entry = cols->data;
  1879.       palette_entries_add_entry (new_entries,
  1880.                      entry->name,
  1881.                      entry->color[0],
  1882.                      entry->color[1],
  1883.                      entry->color[2]);
  1884.       cols = cols->next;
  1885.     }
  1886.       sel_list = sel_list->next;
  1887.     }
  1888.  
  1889.   palette_insert_all (new_entries);
  1890. }
  1891.  
  1892. static void
  1893. palette_dialog_merge_callback (GtkWidget *widget,
  1894.                    gpointer   data)
  1895. {
  1896.   GtkWidget *qbox;
  1897.  
  1898.   qbox = gimp_query_string_box (_("Merge Palette"),
  1899.                 gimp_standard_help_func,
  1900.                 "dialogs/palette_editor/merge_palette.html",
  1901.                 _("Enter a name for merged palette"),
  1902.                 NULL,
  1903.                 NULL, NULL,
  1904.                 palette_dialog_merge_entries_callback,
  1905.                 data);
  1906.   gtk_widget_show (qbox);
  1907. }
  1908.  
  1909. /*  the palette & palette edit action area callbacks  ************************/
  1910.  
  1911. static void
  1912. palette_dialog_save_callback (GtkWidget *widget,
  1913.                   gpointer   data)
  1914. {
  1915.   palette_save_palettes ();
  1916. }
  1917.  
  1918. static void
  1919. palette_dialog_refresh_callback (GtkWidget *widget,
  1920.                  gpointer   data)
  1921. {
  1922.   palette_refresh_all ();
  1923. }
  1924.  
  1925. static void
  1926. palette_dialog_edit_callback (GtkWidget *widget,
  1927.                   gpointer   data)
  1928. {
  1929.   PaletteEntries *p_entries = NULL;
  1930.   PaletteDialog *palette;
  1931.   GList *sel_list;
  1932.  
  1933.   palette = (PaletteDialog *) data;
  1934.   sel_list = GTK_CLIST (palette->clist)->selection;
  1935.  
  1936.   if (sel_list)
  1937.     {
  1938.       p_entries = 
  1939.     (PaletteEntries *) gtk_clist_get_row_data (GTK_CLIST (palette->clist),
  1940.                            GPOINTER_TO_INT (sel_list->data));
  1941.     }
  1942.  
  1943.   palette_create_edit (p_entries);
  1944. }
  1945.  
  1946. static void
  1947. palette_dialog_close_callback (GtkWidget *widget,
  1948.                    gpointer   data)
  1949. {
  1950.   PaletteDialog *palette;
  1951.  
  1952.   palette = data;
  1953.  
  1954.   if (palette)
  1955.     {
  1956.       if (palette->color_notebook_active)
  1957.     {
  1958.       color_notebook_hide (palette->color_notebook);
  1959.       palette->color_notebook_active = FALSE;
  1960.     }
  1961.  
  1962.       if (palette == top_level_edit_palette && import_dialog)
  1963.     {
  1964.       gtk_widget_destroy (import_dialog->dialog);
  1965.       g_free (import_dialog);
  1966.       import_dialog = NULL;
  1967.     }
  1968.       
  1969.       if (GTK_WIDGET_VISIBLE (palette->shell))
  1970.     gtk_widget_hide (palette->shell);
  1971.     }
  1972. }
  1973.  
  1974. /*  the palette dialog color dnd callbacks  **********************************/
  1975.  
  1976. static void
  1977. palette_dialog_drag_color (GtkWidget *widget,
  1978.                guchar    *r,
  1979.                guchar    *g,
  1980.                guchar    *b,
  1981.                gpointer   data)
  1982. {
  1983.   PaletteDialog *palette;
  1984.  
  1985.   palette = (PaletteDialog *) data;
  1986.  
  1987.   if (palette && palette->entries && palette->dnd_color)
  1988.     {
  1989.       *r = (guchar) palette->dnd_color->color[0];
  1990.       *g = (guchar) palette->dnd_color->color[1];
  1991.       *b = (guchar) palette->dnd_color->color[2];
  1992.     }
  1993.   else
  1994.     {
  1995.       *r = *g = *b = 0;
  1996.     }
  1997. }
  1998.  
  1999. static void
  2000. palette_dialog_drop_color (GtkWidget *widget,
  2001.                guchar      r,
  2002.                guchar      g,
  2003.                guchar      b,
  2004.                gpointer    data)
  2005. {
  2006.   PaletteDialog *palette;
  2007.  
  2008.   palette = (PaletteDialog *) data;
  2009.  
  2010.   if (palette && palette->entries)
  2011.     {
  2012.       palette->color =
  2013.     palette_entries_add_entry (palette->entries, _("Untitled"), r, g, b);
  2014.  
  2015.       palette_update_all (palette->entries);
  2016.     }
  2017. }
  2018.  
  2019. /*  the palette & palette edit dialog constructor  ***************************/
  2020.  
  2021. PaletteDialog *
  2022. palette_dialog_new (gboolean editor)
  2023. {
  2024.   PaletteDialog *palette;
  2025.   GtkWidget *hbox;
  2026.   GtkWidget *hbox2;
  2027.   GtkWidget *vbox;
  2028.   GtkWidget *scrolledwindow;
  2029.   GtkWidget *palette_region;
  2030.   GtkWidget *entry;
  2031.   GtkWidget *eventbox;
  2032.   GtkWidget *alignment;
  2033.   GtkWidget *frame;
  2034.   GtkWidget *button;
  2035.   gchar     *titles[3];
  2036.  
  2037.   palette = g_new0 (PaletteDialog, 1);
  2038.   palette->entries               = default_palette_entries;
  2039.   palette->zoom_factor           = 1.0;
  2040.   palette->columns               = COLUMNS;
  2041.   palette->columns_valid         = TRUE;
  2042.   palette->freeze_update         = FALSE;
  2043.  
  2044.   if (!editor)
  2045.     {
  2046.       palette->shell =
  2047.     gimp_dialog_new (_("Color Palette Edit"), "color_palette_edit",
  2048.              gimp_standard_help_func,
  2049.              "dialogs/palette_editor/palette_editor.html",
  2050.              GTK_WIN_POS_NONE,
  2051.              FALSE, TRUE, FALSE,
  2052.  
  2053.              _("Save"), palette_dialog_save_callback,
  2054.              palette, NULL, NULL, FALSE, FALSE,
  2055.              _("Refresh"), palette_dialog_refresh_callback,
  2056.              palette, NULL, NULL, FALSE, FALSE,
  2057.              _("Close"), palette_dialog_close_callback,
  2058.              palette, NULL, NULL, TRUE, TRUE,
  2059.  
  2060.              NULL);
  2061.     }
  2062.   else
  2063.     {
  2064.       palette->shell =
  2065.     gimp_dialog_new (_("Color Palette"), "color_palette",
  2066.              gimp_standard_help_func,
  2067.              "dialogs/palette_selection.html",
  2068.              GTK_WIN_POS_NONE,
  2069.              FALSE, TRUE, FALSE,
  2070.  
  2071.              _("Edit"), palette_dialog_edit_callback,
  2072.              palette, NULL, NULL, FALSE, FALSE,
  2073.              _("Close"), palette_dialog_close_callback,
  2074.              palette, NULL, NULL, TRUE, TRUE,
  2075.  
  2076.              NULL);
  2077.      }
  2078.  
  2079.   /*  The main container widget  */
  2080.   if (editor)
  2081.     {
  2082.       hbox = gtk_notebook_new ();
  2083.       gtk_container_set_border_width (GTK_CONTAINER (hbox), 1);
  2084.     }
  2085.   else
  2086.     {
  2087.       hbox = gtk_hbox_new (FALSE, 4);
  2088.       gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  2089.     }
  2090.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (palette->shell)->vbox), hbox);
  2091.   gtk_widget_show (hbox);
  2092.  
  2093.   vbox = gtk_vbox_new (FALSE, 2);
  2094.   gtk_widget_show (vbox);
  2095.  
  2096.   palette->scrolled_window =
  2097.     scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
  2098.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
  2099.                   GTK_POLICY_AUTOMATIC,
  2100.                   GTK_POLICY_ALWAYS);
  2101.   gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
  2102.   gtk_widget_show (scrolledwindow);
  2103.  
  2104.   eventbox = gtk_event_box_new ();
  2105.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledwindow),
  2106.                      eventbox);
  2107.   gtk_signal_connect (GTK_OBJECT (eventbox), "button_press_event",
  2108.               GTK_SIGNAL_FUNC (palette_dialog_eventbox_button_press),
  2109.               palette);
  2110.   gtk_widget_show (eventbox);
  2111.  
  2112.   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); 
  2113.   gtk_container_add (GTK_CONTAINER (eventbox), alignment);
  2114.   gtk_widget_show (alignment);
  2115.  
  2116.   palette->color_area = palette_region = gtk_preview_new (GTK_PREVIEW_COLOR);
  2117.   gtk_preview_set_dither (GTK_PREVIEW (palette->color_area),
  2118.               GDK_RGB_DITHER_MAX);
  2119.   gtk_preview_size (GTK_PREVIEW (palette_region), PREVIEW_WIDTH, PREVIEW_HEIGHT);
  2120.   
  2121.   gtk_widget_set_events (palette_region, PALETTE_EVENT_MASK);
  2122.   gtk_signal_connect (GTK_OBJECT (palette->color_area), "event",
  2123.               GTK_SIGNAL_FUNC (palette_dialog_color_area_events),
  2124.               palette);
  2125.  
  2126.   gtk_container_add (GTK_CONTAINER (alignment), palette_region);
  2127.   gtk_widget_show (palette_region);
  2128.  
  2129.   /*  dnd stuff  */
  2130.   gtk_drag_source_set (palette_region,
  2131.                        GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  2132.                        color_palette_target_table, n_color_palette_targets,
  2133.                        GDK_ACTION_COPY | GDK_ACTION_MOVE);
  2134.   gimp_dnd_color_source_set (palette_region, palette_dialog_drag_color, palette);
  2135.  
  2136.   gtk_drag_dest_set (alignment,
  2137.                      GTK_DEST_DEFAULT_HIGHLIGHT |
  2138.                      GTK_DEST_DEFAULT_MOTION |
  2139.                      GTK_DEST_DEFAULT_DROP,
  2140.                      color_palette_target_table, n_color_palette_targets,
  2141.                      GDK_ACTION_COPY);
  2142.   gimp_dnd_color_dest_set (alignment, palette_dialog_drop_color, palette);
  2143.  
  2144.   /*  The color name entry  */
  2145.   hbox2 = gtk_hbox_new (FALSE, 2);
  2146.   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
  2147.   gtk_widget_show (hbox2);
  2148.  
  2149.   entry = palette->color_name = gtk_entry_new ();
  2150.   gtk_widget_show (entry);
  2151.   gtk_box_pack_start (GTK_BOX (hbox2), entry, TRUE, TRUE, 0);
  2152.   gtk_entry_set_text (GTK_ENTRY (entry), _("Undefined"));
  2153.   gtk_widget_set_sensitive (entry, FALSE);
  2154.   palette->entry_sig_id =
  2155.     gtk_signal_connect (GTK_OBJECT (entry), "changed",
  2156.             GTK_SIGNAL_FUNC (palette_dialog_color_name_entry_changed),
  2157.             palette);
  2158.  
  2159.   /*  + and - buttons  */
  2160.   button = gimp_pixmap_button_new (zoom_in_xpm, NULL);
  2161.   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
  2162.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2163.               GTK_SIGNAL_FUNC (palette_dialog_zoomin_callback),
  2164.               (gpointer) palette);
  2165.   gtk_widget_show (button);
  2166.  
  2167.   button = gimp_pixmap_button_new (zoom_out_xpm, NULL);
  2168.   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
  2169.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2170.               GTK_SIGNAL_FUNC (palette_dialog_zoomout_callback),
  2171.               (gpointer) palette);
  2172.   gtk_widget_show (button);
  2173.   
  2174.   /*  clist preview of palettes  */
  2175.   scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
  2176.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
  2177.                   GTK_POLICY_AUTOMATIC,
  2178.                   GTK_POLICY_ALWAYS);
  2179.  
  2180.   if (editor)
  2181.     {
  2182.       gtk_notebook_append_page (GTK_NOTEBOOK (hbox), vbox,
  2183.                 gtk_label_new (_("Palette")));
  2184.       gtk_notebook_append_page (GTK_NOTEBOOK (hbox), scrolledwindow,
  2185.                 gtk_label_new (_("Select")));
  2186.     }
  2187.   else
  2188.     {
  2189.       gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  2190.       gtk_box_pack_start (GTK_BOX (hbox), scrolledwindow, TRUE, TRUE, 0);
  2191.     }
  2192.  
  2193.   gtk_widget_show (scrolledwindow);
  2194.  
  2195.   titles[0] = _("Palette");
  2196.   titles[1] = _("Ncols");
  2197.   titles[2] = _("Name");
  2198.   palette->clist = gtk_clist_new_with_titles (3, titles);
  2199.   gtk_widget_set_usize (palette->clist, 203, 203);
  2200.   gtk_clist_set_row_height (GTK_CLIST (palette->clist), SM_PREVIEW_HEIGHT + 2);
  2201.   gtk_clist_set_column_width (GTK_CLIST (palette->clist), 0, SM_PREVIEW_WIDTH+2);
  2202.   gtk_clist_column_titles_passive (GTK_CLIST (palette->clist));
  2203.   gtk_container_add (GTK_CONTAINER (scrolledwindow), palette->clist);
  2204.  
  2205.   if (!editor)
  2206.     gtk_clist_set_selection_mode (GTK_CLIST (palette->clist),
  2207.                   GTK_SELECTION_EXTENDED);
  2208.  
  2209.   gtk_signal_connect (GTK_OBJECT (palette->clist), "select_row",
  2210.               GTK_SIGNAL_FUNC (palette_dialog_list_item_update),
  2211.               (gpointer) palette);
  2212.   gtk_widget_show (palette->clist);
  2213.   
  2214.   if (!editor) 
  2215.     {
  2216.       frame = gtk_frame_new (_("Palette Ops"));
  2217.       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  2218.       gtk_widget_show (frame); 
  2219.  
  2220.       vbox = gtk_vbox_new (FALSE, 2);
  2221.       gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  2222.       gtk_container_add (GTK_CONTAINER (frame), vbox);
  2223.       gtk_widget_show (vbox);
  2224.       
  2225.       button = gtk_button_new_with_label (_("New"));
  2226.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2227.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2228.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2229.               GTK_SIGNAL_FUNC (palette_dialog_new_callback),
  2230.               (gpointer) palette);
  2231.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2232.       gimp_help_set_help_data (button, NULL,
  2233.                    "dialogs/palette_editor/new_palette.html");
  2234.       gtk_widget_show (button);
  2235.  
  2236.       button = gtk_button_new_with_label (_("Delete"));
  2237.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2238.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2239.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2240.               GTK_SIGNAL_FUNC (palette_dialog_delete_callback),
  2241.               (gpointer) palette);
  2242.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2243.       gimp_help_set_help_data (button, NULL,
  2244.                    "dialogs/palette_editor/delete_palette.html");
  2245.       gtk_widget_show (button);
  2246.       
  2247.       button = gtk_button_new_with_label (_("Import"));
  2248.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2249.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2250.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2251.               GTK_SIGNAL_FUNC (palette_dialog_import_callback),
  2252.               (gpointer) palette);
  2253.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2254.       gimp_help_set_help_data (button, NULL,
  2255.                    "dialogs/palette_editor/import_palette.html");
  2256.       gtk_widget_show (button);
  2257.  
  2258.       button = gtk_button_new_with_label (_("Merge"));
  2259.       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  2260.       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  2261.       gtk_signal_connect (GTK_OBJECT (button), "clicked",
  2262.               GTK_SIGNAL_FUNC (palette_dialog_merge_callback),
  2263.               (gpointer) palette);
  2264.       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  2265.       gimp_help_set_help_data (button, NULL,
  2266.                    "dialogs/palette_editor/merge_palette.html");
  2267.       gtk_widget_show (button);
  2268.     }
  2269.  
  2270.   gtk_widget_realize (palette->shell);
  2271.  
  2272.   palette->gc = gdk_gc_new (palette->shell->window);
  2273.  
  2274.   /*  fill the clist  */
  2275.   palette_clist_init (palette->clist, palette->shell, palette->gc);
  2276.   palette_dialog_clist_scroll_to_current (palette);
  2277.  
  2278.   palette_dialog_create_popup_menu (palette);
  2279.  
  2280.   return palette;
  2281. }
  2282.  
  2283. /*****************************************************************************/
  2284. /*  palette import dialog functions  *****************************************/
  2285.  
  2286. /*  functions to create & update the import dialog's gradient selection  *****/
  2287.  
  2288. static void
  2289. palette_import_select_grad_callback (GtkWidget *widget,
  2290.                      gpointer   data)
  2291. {
  2292.   /*  Popup grad edit box ....  */
  2293.   gradient_dialog_create ();
  2294. }
  2295.  
  2296. static void
  2297. palette_import_fill_grad_preview (GtkWidget  *preview,
  2298.                   gradient_t *gradient)
  2299. {
  2300.   guchar buffer[3*IMPORT_PREVIEW_WIDTH];
  2301.   gint loop;
  2302.   guchar *p = buffer;
  2303.   gdouble  dx, cur_x;
  2304.   gdouble  r, g, b, a;
  2305.  
  2306.   dx    = 1.0/ (IMPORT_PREVIEW_WIDTH - 1);
  2307.   cur_x = 0;
  2308.  
  2309.   for (loop = 0 ; loop < IMPORT_PREVIEW_WIDTH; loop++)
  2310.     {
  2311.       gradient_get_color_at (gradient, cur_x, &r, &g, &b, &a);
  2312.       *p++ = r * 255.0;
  2313.       *p++ = g * 255.0;
  2314.       *p++ = b * 255.0;
  2315.       cur_x += dx;
  2316.     }
  2317.  
  2318.   for (loop = 0 ; loop < IMPORT_PREVIEW_HEIGHT; loop++)
  2319.     {
  2320.       gtk_preview_draw_row (GTK_PREVIEW (preview), buffer, 0, loop,
  2321.                 IMPORT_PREVIEW_WIDTH);
  2322.     }
  2323.  
  2324.   gtk_widget_draw (preview, NULL);
  2325. }
  2326.  
  2327. static void
  2328. palette_import_gradient_update (GimpContext *context,
  2329.                 gradient_t  *gradient,
  2330.                 gpointer     data)
  2331. {
  2332.   if (import_dialog && import_dialog->import_type == GRAD_IMPORT)
  2333.     {
  2334.       /* redraw gradient */
  2335.       palette_import_fill_grad_preview (import_dialog->preview, gradient);
  2336.       gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), gradient->name);
  2337.     }
  2338. }
  2339.  
  2340. /*  functions to create & update the import dialog's image selection  ********/
  2341.  
  2342. static void
  2343. palette_import_gimlist_cb (gpointer im,
  2344.                gpointer data)
  2345. {
  2346.   GSList** l;
  2347.  
  2348.   l = (GSList**) data;
  2349.   *l = g_slist_prepend (*l, im);
  2350. }
  2351.  
  2352. static void
  2353. palette_import_gimlist_indexed_cb (gpointer im,
  2354.                    gpointer data)
  2355. {
  2356.   GimpImage *gimage = GIMP_IMAGE (im);
  2357.   GSList** l;
  2358.  
  2359.   if (gimage_base_type (gimage) == INDEXED)
  2360.     {
  2361.       l = (GSList**) data;
  2362.       *l = g_slist_prepend (*l, im);
  2363.     }
  2364. }
  2365.  
  2366. static void
  2367. palette_import_update_image_preview (GimpImage *gimage)
  2368. {
  2369.   TempBuf * preview_buf;
  2370.   gchar *src, *buf;
  2371.   gint x,y,has_alpha;
  2372.   gint sel_width, sel_height;
  2373.   gint pwidth, pheight;
  2374.  
  2375.   import_dialog->gimage = gimage;
  2376.  
  2377.   /* Calculate preview size */
  2378.  
  2379.   sel_width = gimage->width;
  2380.   sel_height = gimage->height;
  2381.  
  2382.   if (sel_width > sel_height) {
  2383.     pwidth  = MIN(sel_width, IMPORT_PREVIEW_WIDTH);
  2384.     pheight = sel_height * pwidth / sel_width;
  2385.   } else {
  2386.     pheight = MIN(sel_height, IMPORT_PREVIEW_HEIGHT);
  2387.     pwidth  = sel_width * pheight / sel_height;
  2388.   }
  2389.   
  2390.   /* Min size is 2 */
  2391.   preview_buf = gimp_image_construct_composite_preview (gimage,
  2392.                             MAX (pwidth, 2),
  2393.                             MAX (pheight, 2));
  2394.  
  2395.   gtk_preview_size (GTK_PREVIEW (import_dialog->preview),
  2396.             preview_buf->width,
  2397.             preview_buf->height);
  2398.  
  2399.   buf = g_new (gchar,  IMPORT_PREVIEW_WIDTH * 3);
  2400.   src = (gchar *) temp_buf_data (preview_buf);
  2401.   has_alpha = (preview_buf->bytes == 2 || preview_buf->bytes == 4);
  2402.   for (y = 0; y <preview_buf->height ; y++)
  2403.     {
  2404.       if (preview_buf->bytes == (1+has_alpha))
  2405.     for (x = 0; x < preview_buf->width; x++)
  2406.       {
  2407.         buf[x*3+0] = src[x];
  2408.         buf[x*3+1] = src[x];
  2409.         buf[x*3+2] = src[x];
  2410.       }
  2411.       else
  2412.     for (x = 0; x < preview_buf->width; x++)
  2413.       {
  2414.         gint stride = 3 + has_alpha;
  2415.         buf[x*3+0] = src[x*stride+0];
  2416.         buf[x*3+1] = src[x*stride+1];
  2417.         buf[x*3+2] = src[x*stride+2];
  2418.       }
  2419.       gtk_preview_draw_row (GTK_PREVIEW (import_dialog->preview),
  2420.                 (guchar *)buf, 0, y, preview_buf->width);
  2421.       src += preview_buf->width * preview_buf->bytes;
  2422.     }
  2423.  
  2424.   g_free (buf);
  2425.   temp_buf_free (preview_buf);
  2426.  
  2427.   gtk_widget_hide (import_dialog->preview);
  2428.   gtk_widget_draw (import_dialog->preview, NULL); 
  2429.   gtk_widget_show (import_dialog->preview);
  2430. }
  2431.  
  2432. static void
  2433. palette_import_image_sel_callback (GtkWidget *widget,
  2434.                    gpointer   data)
  2435. {
  2436.   GimpImage *gimage;
  2437.   gchar *lab;
  2438.  
  2439.   gimage = GIMP_IMAGE (data);
  2440.   palette_import_update_image_preview (gimage);
  2441.  
  2442.   lab = g_strdup_printf ("%s-%d",
  2443.              g_basename (gimage_filename (import_dialog->gimage)),
  2444.              pdb_image_to_id (import_dialog->gimage));
  2445.  
  2446.   gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
  2447. }
  2448.  
  2449. static void
  2450. palette_import_image_menu_add (GimpImage *gimage)
  2451. {
  2452.   GtkWidget *menuitem;
  2453.   gchar *lab = g_strdup_printf ("%s-%d",
  2454.                 g_basename (gimage_filename (gimage)),
  2455.                 pdb_image_to_id (gimage));
  2456.   menuitem = gtk_menu_item_new_with_label (lab);
  2457.   gtk_widget_show (menuitem);
  2458.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  2459.               GTK_SIGNAL_FUNC (palette_import_image_sel_callback),
  2460.               gimage);
  2461.   gtk_menu_append (GTK_MENU (import_dialog->optionmenu1_menu), menuitem);
  2462. }
  2463.  
  2464. /* Last Param gives us control over what goes in the menu on a delete oper */
  2465. static void
  2466. palette_import_image_menu_activate (gint        redo,
  2467.                     ImportType  type,
  2468.                     GimpImage  *del_image)
  2469. {
  2470.   GSList *list=NULL;
  2471.   gint num_images;
  2472.   GimpImage *last_img = NULL;
  2473.   GimpImage *first_img = NULL;
  2474.   gint act_num = -1;
  2475.   gint count = 0;
  2476.   gchar *lab;
  2477.  
  2478.   if (!import_dialog)
  2479.     return;
  2480.  
  2481.   if (import_dialog->import_type == type && !redo)
  2482.     return;
  2483.  
  2484.   /* Destroy existing widget if necessary */
  2485.   if (import_dialog->image_list)
  2486.     {
  2487.       if (redo) /* Preserve settings in this case */
  2488.         last_img = import_dialog->gimage;
  2489.       gtk_widget_hide (import_dialog->image_list);
  2490.       gtk_widget_destroy (import_dialog->image_list);
  2491.       import_dialog->image_list = NULL;
  2492.     }
  2493.  
  2494.   import_dialog->import_type= type;
  2495.  
  2496.   /* Get list of images */
  2497.   if (import_dialog->import_type == INDEXED_IMPORT)
  2498.     {
  2499.       gimage_foreach (palette_import_gimlist_indexed_cb, &list);
  2500.     }
  2501.   else
  2502.     {
  2503.       gimage_foreach (palette_import_gimlist_cb, &list);
  2504.     }
  2505.  
  2506.   num_images = g_slist_length (list);
  2507.       
  2508.   if (num_images)
  2509.     {
  2510.       gint i;
  2511.       GtkWidget *optionmenu1;
  2512.       GtkWidget *optionmenu1_menu;
  2513.  
  2514.       import_dialog->image_list = optionmenu1 = gtk_option_menu_new ();
  2515.       gtk_widget_set_usize (optionmenu1, IMPORT_PREVIEW_WIDTH, -1);
  2516.       import_dialog->optionmenu1_menu = optionmenu1_menu = gtk_menu_new ();
  2517.  
  2518.       for (i = 0; i < num_images; i++, list = g_slist_next (list))
  2519.         {
  2520.           if (GIMP_IMAGE (list->data) != del_image)
  2521.             {
  2522.           if (first_img == NULL)
  2523.             first_img = GIMP_IMAGE (list->data);
  2524.           palette_import_image_menu_add (GIMP_IMAGE (list->data));
  2525.           if (last_img == GIMP_IMAGE (list->data))
  2526.             act_num = count;
  2527.           else
  2528.             count++;
  2529.         }
  2530.     }
  2531.  
  2532.       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu1),
  2533.                 optionmenu1_menu);
  2534.       gtk_widget_hide (import_dialog->select);
  2535.       gtk_box_pack_start (GTK_BOX (import_dialog->select_area),
  2536.                       optionmenu1, FALSE, FALSE, 0);
  2537.  
  2538.       if(last_img != NULL && last_img != del_image)
  2539.         palette_import_update_image_preview (last_img);
  2540.       else if (first_img != NULL)
  2541.     palette_import_update_image_preview (first_img);
  2542.  
  2543.       gtk_widget_show (optionmenu1);
  2544.  
  2545.       /* reset to last one */
  2546.       if (redo && act_num >= 0)
  2547.         {
  2548.            gchar *lab = g_strdup_printf ("%s-%d",
  2549.              g_basename (gimage_filename (import_dialog->gimage)),
  2550.              pdb_image_to_id (import_dialog->gimage));
  2551.  
  2552.            gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu1), act_num);
  2553.            gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
  2554.     }
  2555.     }
  2556.   g_slist_free (list);
  2557.  
  2558.   lab = g_strdup_printf ("%s-%d",
  2559.              g_basename (gimage_filename (import_dialog->gimage)),
  2560.              pdb_image_to_id (import_dialog->gimage));
  2561.  
  2562.   gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), lab);
  2563. }
  2564.  
  2565. /*  the import source menu item callbacks  ***********************************/
  2566.  
  2567. static void
  2568. palette_import_grad_callback (GtkWidget *widget,
  2569.                   gpointer   data)
  2570. {
  2571.   if (import_dialog)
  2572.     {
  2573.       gradient_t *gradient;
  2574.  
  2575.       gradient = gimp_context_get_gradient (gimp_context_get_user ());
  2576.  
  2577.       import_dialog->import_type = GRAD_IMPORT;
  2578.       if (import_dialog->image_list)
  2579.     {
  2580.       gtk_widget_hide (import_dialog->image_list);
  2581.       gtk_widget_destroy (import_dialog->image_list);
  2582.       import_dialog->image_list = NULL;
  2583.     }
  2584.       gtk_widget_show (import_dialog->select);
  2585.       palette_import_fill_grad_preview (import_dialog->preview, gradient);
  2586.  
  2587.       gtk_entry_set_text (GTK_ENTRY (import_dialog->entry), gradient->name);
  2588.       gtk_widget_set_sensitive (import_dialog->threshold_scale, FALSE);
  2589.       gtk_widget_set_sensitive (import_dialog->threshold_text, FALSE);
  2590.     }
  2591. }
  2592.  
  2593. static void
  2594. palette_import_image_callback (GtkWidget *widget,
  2595.                    gpointer   data)
  2596. {
  2597.   palette_import_image_menu_activate (FALSE, IMAGE_IMPORT, NULL);
  2598.   gtk_widget_set_sensitive (import_dialog->threshold_scale, TRUE);
  2599.   gtk_widget_set_sensitive (import_dialog->threshold_text, TRUE);
  2600. }
  2601.  
  2602. static void
  2603. palette_import_indexed_callback (GtkWidget *widget,
  2604.                  gpointer   data)
  2605. {
  2606.   palette_import_image_menu_activate (FALSE, INDEXED_IMPORT, NULL);
  2607.   gtk_widget_set_sensitive (import_dialog->threshold_scale, FALSE);
  2608.   gtk_widget_set_sensitive (import_dialog->threshold_text, FALSE);
  2609. }
  2610.  
  2611. /*  functions & callbacks to keep the import dialog uptodate  ****************/
  2612.  
  2613. static gint
  2614. palette_import_image_count (ImportType type)
  2615. {
  2616.   GSList *list=NULL;
  2617.   gint num_images = 0;
  2618.  
  2619.   if (type == INDEXED_IMPORT)
  2620.     {
  2621.       gimage_foreach (palette_import_gimlist_indexed_cb, &list);
  2622.     }
  2623.   else
  2624.     {
  2625.       gimage_foreach (palette_import_gimlist_cb, &list);
  2626.     }
  2627.  
  2628.   num_images = g_slist_length (list);
  2629.  
  2630.   g_slist_free (list);
  2631.  
  2632.   return num_images;
  2633. }
  2634.  
  2635. static void
  2636. palette_import_image_new (GimpSet   *set,
  2637.               GimpImage *gimage,
  2638.               gpointer   data)
  2639. {
  2640.   if (!import_dialog)
  2641.     return;
  2642.  
  2643.   if (!GTK_WIDGET_IS_SENSITIVE (import_dialog->image_menu_item_image))
  2644.     {
  2645.       gtk_widget_set_sensitive (import_dialog->image_menu_item_image, TRUE);
  2646.       return;
  2647.     }
  2648.  
  2649.   if (!GTK_WIDGET_IS_SENSITIVE (import_dialog->image_menu_item_indexed) &&
  2650.       gimage_base_type(gimage) == INDEXED)
  2651.     {
  2652.       gtk_widget_set_sensitive (import_dialog->image_menu_item_indexed, TRUE);
  2653.       return;
  2654.     }
  2655.  
  2656.   /* Now fill in the names if image menu shown */
  2657.   if (import_dialog->import_type == IMAGE_IMPORT ||
  2658.       import_dialog->import_type == INDEXED_IMPORT)
  2659.     {
  2660.       palette_import_image_menu_activate (TRUE, import_dialog->import_type,
  2661.                       NULL);
  2662.     }
  2663. }
  2664.  
  2665. static void
  2666. palette_import_image_destroyed (GimpSet   *set,
  2667.                 GimpImage *gimage,
  2668.                 gpointer   data)
  2669. {
  2670.   if (!import_dialog)
  2671.     return;
  2672.  
  2673.   if (palette_import_image_count (import_dialog->import_type) <= 1)
  2674.     {
  2675.       /* Back to gradient type */
  2676.       gtk_option_menu_set_history (GTK_OPTION_MENU (import_dialog->type_option), 0);
  2677.       palette_import_grad_callback (NULL, NULL);
  2678.       if (import_dialog->image_menu_item_image)
  2679.     gtk_widget_set_sensitive (import_dialog->image_menu_item_image, FALSE);
  2680.       return;
  2681.     }
  2682.  
  2683.   if (import_dialog->import_type == IMAGE_IMPORT ||
  2684.       import_dialog->import_type == INDEXED_IMPORT)
  2685.     {
  2686.       palette_import_image_menu_activate (TRUE, import_dialog->import_type,
  2687.                       gimage);
  2688.     }
  2689. }
  2690.  
  2691. void
  2692. palette_import_image_renamed (GimpImage* gimage)
  2693. {
  2694.   /* Now fill in the names if image menu shown */
  2695.   if (import_dialog && (import_dialog->import_type == IMAGE_IMPORT ||
  2696.       import_dialog->import_type == INDEXED_IMPORT))
  2697.     {
  2698.       palette_import_image_menu_activate (TRUE, import_dialog->import_type,
  2699.                       NULL);
  2700.     }
  2701. }
  2702.  
  2703. /*  create a palette from a gradient  ****************************************/
  2704.  
  2705. static void
  2706. palette_import_create_from_grad (gchar *name)
  2707. {
  2708.   PaletteEntries *entries;
  2709.   gradient_t *gradient;
  2710.  
  2711.   gradient = gimp_context_get_gradient (gimp_context_get_user ());
  2712.  
  2713.   if (gradient)
  2714.     {
  2715.       /* Add names to entry */
  2716.       gdouble  dx, cur_x;
  2717.       gdouble  r, g, b, a;
  2718.  
  2719.       gint sample_sz;
  2720.       gint loop;
  2721.  
  2722.       entries = palette_entries_new (name);
  2723.       sample_sz = (gint) import_dialog->sample->value;  
  2724.  
  2725.       dx    = 1.0 / (sample_sz - 1);
  2726.       cur_x = 0;
  2727.       
  2728.       for (loop = 0; loop < sample_sz; loop++)
  2729.     {
  2730.       gradient_get_color_at (gradient, cur_x, &r, &g, &b, &a);
  2731.       r = r * 255.0;
  2732.       g = g * 255.0;
  2733.       b = b * 255.0;
  2734.       cur_x += dx;
  2735.       palette_entries_add_entry (entries, _("Untitled"),
  2736.                      (gint) r, (gint) g, (gint) b);
  2737.     }
  2738.  
  2739.       palette_insert_all (entries);
  2740.     }
  2741. }
  2742.  
  2743. /*  create a palette from a non-indexed image  *******************************/
  2744.  
  2745. typedef struct _ImgColors ImgColors;
  2746.  
  2747. struct _ImgColors
  2748. {
  2749.   guint count;
  2750.   guint r_adj;
  2751.   guint g_adj;
  2752.   guint b_adj;
  2753.   guchar r;
  2754.   guchar g;
  2755.   guchar b;
  2756. };
  2757.  
  2758. static gint count_color_entries = 0;
  2759.  
  2760. static GHashTable *
  2761. palette_import_store_colors (GHashTable *h_array, 
  2762.                  guchar     *colors,
  2763.                  guchar     *colors_real, 
  2764.                  gint        sample_sz)
  2765. {
  2766.   gpointer found_color = NULL;
  2767.   ImgColors *new_color;
  2768.   guint key_colors = colors[0]*256*256 + colors[1]*256 + colors[2];
  2769.  
  2770.   if(h_array == NULL)
  2771.     {
  2772.       h_array = g_hash_table_new (g_direct_hash, g_direct_equal);
  2773.       count_color_entries = 0;
  2774.     }
  2775.   else
  2776.     {
  2777.       found_color = g_hash_table_lookup (h_array, (gpointer) key_colors);
  2778.     }
  2779.  
  2780.   if (found_color == NULL)
  2781.     {
  2782.       if (count_color_entries > MAX_IMAGE_COLORS)
  2783.     {
  2784.       /* Don't add any more new ones */
  2785.       return h_array;
  2786.     }
  2787.  
  2788.       count_color_entries++;
  2789.  
  2790.       new_color = g_new (ImgColors, 1);
  2791.  
  2792.       new_color->count = 1;
  2793.       new_color->r_adj = 0;
  2794.       new_color->g_adj = 0;
  2795.       new_color->b_adj = 0;
  2796.       new_color->r = colors[0];
  2797.       new_color->g = colors[1];
  2798.       new_color->b = colors[2];
  2799.  
  2800.       g_hash_table_insert (h_array, (gpointer) key_colors, new_color);
  2801.     }
  2802.   else
  2803.     {
  2804.       new_color = (ImgColors *) found_color;
  2805.       if(new_color->count < (G_MAXINT - 1))
  2806.     new_color->count++;
  2807.       
  2808.       /* Now do the adjustments ...*/
  2809.       new_color->r_adj += (colors_real[0] - colors[0]);
  2810.       new_color->g_adj += (colors_real[1] - colors[1]);
  2811.       new_color->b_adj += (colors_real[2] - colors[2]);
  2812.  
  2813.       /* Boundary conditions */
  2814.       if(new_color->r_adj > (G_MAXINT - 255))
  2815.     new_color->r_adj /= new_color->count;
  2816.  
  2817.       if(new_color->g_adj > (G_MAXINT - 255))
  2818.     new_color->g_adj /= new_color->count;
  2819.  
  2820.       if(new_color->b_adj > (G_MAXINT - 255))
  2821.     new_color->b_adj /= new_color->count;
  2822.     }
  2823.  
  2824.   return h_array;
  2825. }
  2826.  
  2827. static void
  2828. palette_import_create_sorted_list (gpointer key,
  2829.                    gpointer value,
  2830.                    gpointer user_data)
  2831. {
  2832.   GSList    **sorted_list = (GSList**) user_data;
  2833.   ImgColors  *color_tab  = (ImgColors *) value;
  2834.  
  2835.   *sorted_list = g_slist_prepend (*sorted_list, color_tab);
  2836. }
  2837.  
  2838. static gint
  2839. palette_import_sort_colors (gconstpointer a,
  2840.                 gconstpointer b)
  2841. {
  2842.   ImgColors *s1 = (ImgColors *) a;
  2843.   ImgColors *s2 = (ImgColors *) b;
  2844.  
  2845.   if(s1->count > s2->count)
  2846.     return -1;
  2847.   if(s1->count < s2->count)
  2848.     return 1;
  2849.  
  2850.   return 0;
  2851. }
  2852.  
  2853. static void
  2854. palette_import_create_image_palette (gpointer data,
  2855.                      gpointer user_data)
  2856. {
  2857.   PaletteEntries *entries = (PaletteEntries *) user_data;
  2858.   ImgColors *color_tab = (ImgColors *) data;
  2859.   gint sample_sz;
  2860.   gchar *lab;
  2861.  
  2862.   sample_sz = (gint) import_dialog->sample->value;  
  2863.  
  2864.   if (entries->n_colors >= sample_sz)
  2865.     return;
  2866.  
  2867.   lab = g_strdup_printf ("%s (occurs %u)", _("Untitled"), color_tab->count);
  2868.  
  2869.   /* Adjust the colors to the mean of the the sample */
  2870.   palette_entries_add_entry
  2871.     (entries, lab, 
  2872.      (gint) color_tab->r + (color_tab->r_adj / color_tab->count), 
  2873.      (gint) color_tab->g + (color_tab->g_adj / color_tab->count), 
  2874.      (gint) color_tab->b + (color_tab->b_adj / color_tab->count));
  2875. }
  2876.  
  2877. static gboolean
  2878. palette_import_color_print_remove (gpointer key,
  2879.                    gpointer value,
  2880.                    gpointer user_data)
  2881. {
  2882.   g_free (value);
  2883.  
  2884.   return TRUE;
  2885. }
  2886.  
  2887. static void
  2888. palette_import_image_make_palette (GHashTable *h_array,
  2889.                    guchar     *name)
  2890. {
  2891.   PaletteEntries *entries;
  2892.   GSList *sorted_list = NULL;
  2893.  
  2894.   g_hash_table_foreach (h_array, palette_import_create_sorted_list,
  2895.             &sorted_list);
  2896.   sorted_list = g_slist_sort (sorted_list, palette_import_sort_colors);
  2897.  
  2898.   entries = palette_entries_new (name);
  2899.   g_slist_foreach (sorted_list, palette_import_create_image_palette, entries);
  2900.  
  2901.   /*  Free up used memory
  2902.    *  Note the same structure is on both the hash list and the sorted
  2903.    *  list. So only delete it once.
  2904.    */
  2905.   g_hash_table_freeze (h_array);
  2906.   g_hash_table_foreach_remove (h_array,
  2907.                    palette_import_color_print_remove, NULL);
  2908.   g_hash_table_thaw (h_array);
  2909.   g_hash_table_destroy (h_array);
  2910.   g_slist_free (sorted_list);
  2911.  
  2912.   palette_insert_all (entries);
  2913. }
  2914.  
  2915. static void
  2916. palette_import_create_from_image (GImage *gimage,
  2917.                   gchar  *pname)
  2918. {
  2919.   PixelRegion imagePR;
  2920.   guchar *image_data;
  2921.   guchar *idata;
  2922.   guchar  rgb[MAX_CHANNELS];
  2923.   guchar  rgb_real[MAX_CHANNELS];
  2924.   gint has_alpha, indexed;
  2925.   gint width, height;
  2926.   gint bytes, alpha;
  2927.   gint i, j;
  2928.   void * pr;
  2929.   gint d_type;
  2930.   GHashTable *store_array = NULL;
  2931.   gint sample_sz;
  2932.   gint threshold = 1;
  2933.  
  2934.   sample_sz = (gint) import_dialog->sample->value;  
  2935.  
  2936.   if (gimage == NULL)
  2937.     return;
  2938.  
  2939.   /*  Get the image information  */
  2940.   bytes = gimage_composite_bytes (gimage);
  2941.   d_type = gimage_composite_type (gimage);
  2942.   has_alpha = (d_type == RGBA_GIMAGE ||
  2943.            d_type == GRAYA_GIMAGE ||
  2944.            d_type == INDEXEDA_GIMAGE);
  2945.   indexed = d_type == INDEXEDA_GIMAGE || d_type == INDEXED_GIMAGE;
  2946.   width = gimage->width;
  2947.   height = gimage->height;
  2948.   pixel_region_init (&imagePR, gimage_composite (gimage), 0, 0,
  2949.              width, height, FALSE);
  2950.  
  2951.   alpha = bytes - 1;
  2952.  
  2953.   threshold = (gint) import_dialog->threshold->value;
  2954.  
  2955.   if(threshold < 1)
  2956.     threshold = 1;
  2957.  
  2958.   /*  iterate over the entire image  */
  2959.   for (pr = pixel_regions_register (1, &imagePR);
  2960.        pr != NULL;
  2961.        pr = pixel_regions_process (pr))
  2962.     {
  2963.       image_data = imagePR.data;
  2964.  
  2965.       for (i = 0; i < imagePR.h; i++)
  2966.     {
  2967.       idata = image_data;
  2968.  
  2969.       for (j = 0; j < imagePR.w; j++)
  2970.         {
  2971.           /*  Get the rgb values for the color  */
  2972.           gimage_get_color (gimage, d_type, rgb, idata);
  2973.           memcpy (rgb_real, rgb, MAX_CHANNELS); /* Structure copy */
  2974.  
  2975.           rgb[0] = (rgb[0] / threshold) * threshold;
  2976.           rgb[1] = (rgb[1] / threshold) * threshold;
  2977.           rgb[2] = (rgb[2] / threshold) * threshold;
  2978.  
  2979.           store_array =
  2980.         palette_import_store_colors (store_array, rgb, rgb_real,
  2981.                          sample_sz);
  2982.  
  2983.           idata += bytes;
  2984.         }
  2985.  
  2986.       image_data += imagePR.rowstride;
  2987.     }
  2988.     }
  2989.  
  2990.   /*  Make palette from the store_array  */
  2991.   palette_import_image_make_palette (store_array, pname);
  2992. }
  2993.  
  2994. /*  create a palette from an indexed image  **********************************/
  2995.  
  2996. static void
  2997. palette_import_create_from_indexed (GImage *gimage,
  2998.                     gchar  *pname)
  2999. {
  3000.   PaletteEntries *entries;
  3001.   gint samples, count;
  3002.  
  3003.   samples = (gint) import_dialog->sample->value;  
  3004.  
  3005.   if (gimage == NULL)
  3006.     return;
  3007.  
  3008.   if (gimage_base_type (gimage) != INDEXED)
  3009.     return;
  3010.  
  3011.   entries = palette_entries_new (pname);
  3012.  
  3013.   for (count= 0; count < samples && count < gimage->num_cols; ++count)
  3014.     {
  3015.       palette_entries_add_entry (entries, NULL,
  3016.                  gimage->cmap[count*3],
  3017.                  gimage->cmap[count*3+1],
  3018.                  gimage->cmap[count*3+2]);
  3019.     }
  3020.  
  3021.   palette_insert_all (entries);
  3022. }
  3023.  
  3024. /*  the palette import action area callbacks  ********************************/
  3025.  
  3026. static void
  3027. palette_import_close_callback (GtkWidget *widget,
  3028.                   gpointer   data)
  3029. {
  3030.   gtk_widget_destroy (import_dialog->dialog);
  3031.   g_free (import_dialog);
  3032.   import_dialog = NULL;
  3033. }
  3034.  
  3035. static void
  3036. palette_import_import_callback (GtkWidget *widget,
  3037.                 gpointer   data)
  3038. {
  3039.   PaletteDialog *palette;
  3040.  
  3041.   palette = data;
  3042.  
  3043.   if (import_dialog)
  3044.     {
  3045.       gchar *pname;
  3046.  
  3047.       pname = gtk_entry_get_text (GTK_ENTRY (import_dialog->entry));
  3048.       if (!pname || !strlen (pname))
  3049.     pname = g_strdup ("tmp");
  3050.       else
  3051.     pname = g_strdup (pname);
  3052.  
  3053.       switch (import_dialog->import_type)
  3054.     {
  3055.     case GRAD_IMPORT:
  3056.       palette_import_create_from_grad (pname);
  3057.       break;
  3058.     case IMAGE_IMPORT:
  3059.       palette_import_create_from_image (import_dialog->gimage, pname);
  3060.       break;
  3061.     case INDEXED_IMPORT:
  3062.       palette_import_create_from_indexed (import_dialog->gimage, pname);
  3063.       break;
  3064.     default:
  3065.       break;
  3066.     }
  3067.       palette_import_close_callback (NULL, NULL);
  3068.     }
  3069. }
  3070.  
  3071. /*  the palette import dialog constructor  ***********************************/
  3072.  
  3073. static ImportDialog *
  3074. palette_import_dialog_new (PaletteDialog *palette)
  3075. {
  3076.   GtkWidget *dialog;
  3077.   GtkWidget *hbox;
  3078.   GtkWidget *frame;
  3079.   GtkWidget *vbox;
  3080.   GtkWidget *table;
  3081.   GtkWidget *label;
  3082.   GtkWidget *spinbutton;
  3083.   GtkWidget *button;
  3084.   GtkWidget *entry;
  3085.   GtkWidget *optionmenu;
  3086.   GtkWidget *optionmenu_menu;
  3087.   GtkWidget *menuitem;
  3088.   GtkWidget *image;
  3089.   GtkWidget *hscale;
  3090.  
  3091.   import_dialog = g_new (ImportDialog, 1);
  3092.   import_dialog->image_list = NULL;
  3093.   import_dialog->gimage     = NULL;
  3094.  
  3095.   import_dialog->dialog = dialog =
  3096.     gimp_dialog_new (_("Import Palette"), "import_palette",
  3097.              gimp_standard_help_func,
  3098.              "dialogs/palette_editor/import_palette.html",
  3099.              GTK_WIN_POS_NONE,
  3100.              FALSE, TRUE, FALSE,
  3101.  
  3102.              _("Import"), palette_import_import_callback,
  3103.              palette, NULL, NULL, FALSE, FALSE,
  3104.              _("Close"), palette_import_close_callback,
  3105.              palette, NULL, NULL, TRUE, TRUE,
  3106.  
  3107.              NULL);
  3108.  
  3109.   /*  The main hbox  */
  3110.   hbox = gtk_hbox_new (FALSE, 4);
  3111.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  3112.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
  3113.   gtk_widget_show (hbox);
  3114.  
  3115.   /*  The "Import" frame  */
  3116.   frame = gtk_frame_new (_("Import"));
  3117.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  3118.   gtk_widget_show (frame);
  3119.  
  3120.   vbox = gtk_vbox_new (FALSE, 2);
  3121.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3122.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  3123.   gtk_widget_show (vbox);
  3124.  
  3125.   table = gtk_table_new (4, 2, FALSE);
  3126.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  3127.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  3128.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  3129.   gtk_widget_show (table);
  3130.  
  3131.   /*  The source's name  */
  3132.   label = gtk_label_new (_("Name:"));
  3133.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3134.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
  3135.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  3136.   gtk_widget_show (label);
  3137.  
  3138.   entry = import_dialog->entry = gtk_entry_new ();
  3139.   gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, 0, 1);
  3140.   {
  3141.     gradient_t* gradient;
  3142.  
  3143.     gradient = gimp_context_get_gradient (gimp_context_get_current ());
  3144.     gtk_entry_set_text (GTK_ENTRY (entry),
  3145.             gradient ? gradient->name : _("new_import"));
  3146.   }
  3147.   gtk_widget_show (entry);
  3148.  
  3149.   /*  The source type  */
  3150.   label = gtk_label_new (_("Source:"));
  3151.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3152.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
  3153.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  3154.   gtk_widget_show (label);
  3155.  
  3156.   optionmenu = import_dialog->type_option = gtk_option_menu_new ();
  3157.   optionmenu_menu = gtk_menu_new ();
  3158.   gtk_table_attach_defaults (GTK_TABLE (table), optionmenu, 1, 2, 1, 2);
  3159.   menuitem = import_dialog->image_menu_item_gradient = 
  3160.     gtk_menu_item_new_with_label (_("Gradient"));
  3161.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  3162.               GTK_SIGNAL_FUNC (palette_import_grad_callback),
  3163.               NULL);
  3164.   gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
  3165.   gtk_widget_show (menuitem);
  3166.  
  3167.   menuitem = import_dialog->image_menu_item_image =
  3168.     gtk_menu_item_new_with_label (_("Image"));
  3169.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  3170.               GTK_SIGNAL_FUNC (palette_import_image_callback),
  3171.               (gpointer) import_dialog);
  3172.   gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
  3173.   gtk_widget_show (menuitem);
  3174.   gtk_widget_set_sensitive (menuitem,
  3175.                 palette_import_image_count (IMAGE_IMPORT) > 0);
  3176.  
  3177.   menuitem = import_dialog->image_menu_item_indexed =
  3178.     gtk_menu_item_new_with_label (_("Indexed Palette"));
  3179.   gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
  3180.                       GTK_SIGNAL_FUNC (palette_import_indexed_callback),
  3181.                       (gpointer) import_dialog);
  3182.   gtk_menu_append (GTK_MENU (optionmenu_menu), menuitem);
  3183.   gtk_widget_show (menuitem);
  3184.   gtk_widget_set_sensitive (menuitem,
  3185.                 palette_import_image_count (INDEXED_IMPORT) > 0);
  3186.  
  3187.   gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), optionmenu_menu);
  3188.   gtk_widget_show (optionmenu);
  3189.  
  3190.   /*  The sample size  */
  3191.   label = gtk_label_new (_("Sample Size:"));
  3192.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3193.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
  3194.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
  3195.   gtk_widget_show (label);
  3196.  
  3197.   import_dialog->sample =
  3198.     GTK_ADJUSTMENT(gtk_adjustment_new (256, 2, 10000, 1, 10, 10));
  3199.   spinbutton = gtk_spin_button_new (import_dialog->sample, 1, 0);
  3200.   gtk_table_attach_defaults (GTK_TABLE (table), spinbutton, 1, 2, 2, 3);
  3201.   gtk_widget_show (spinbutton);
  3202.  
  3203.   /*  The interval  */
  3204.   label = import_dialog->threshold_text = gtk_label_new (_("Interval:"));
  3205.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  3206.   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
  3207.                     GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
  3208.   gtk_widget_set_sensitive(label, FALSE);
  3209.   gtk_widget_show (label);
  3210.  
  3211.   import_dialog->threshold = 
  3212.     GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 128, 1, 1, 1));
  3213.   hscale = import_dialog->threshold_scale = 
  3214.     gtk_hscale_new (import_dialog->threshold);
  3215.   gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_TOP);
  3216.   gtk_scale_set_digits (GTK_SCALE (hscale), 0);
  3217.   gtk_table_attach_defaults (GTK_TABLE (table), hscale, 1, 2, 3, 4);
  3218.   gtk_widget_set_sensitive (hscale, FALSE);
  3219.   gtk_widget_show (hscale);
  3220.  
  3221.   /*  The preview frame  */
  3222.   frame = gtk_frame_new (_("Preview"));
  3223.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  3224.   gtk_widget_show (frame);
  3225.  
  3226.   vbox = import_dialog->select_area = gtk_vbox_new (FALSE, 2);
  3227.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3228.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  3229.   gtk_widget_show (vbox);
  3230.  
  3231.   image = import_dialog->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  3232.   gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX);
  3233.   gtk_preview_size (GTK_PREVIEW (image),
  3234.             IMPORT_PREVIEW_WIDTH, IMPORT_PREVIEW_HEIGHT);
  3235.   gtk_widget_set_usize (image, IMPORT_PREVIEW_WIDTH, IMPORT_PREVIEW_HEIGHT);
  3236.   gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
  3237.   gtk_widget_show (image);
  3238.  
  3239.   button = import_dialog->select = gtk_button_new_with_label (_("Select"));
  3240.   GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
  3241.   gtk_signal_connect (GTK_OBJECT (button), "clicked", 
  3242.               GTK_SIGNAL_FUNC (palette_import_select_grad_callback),
  3243.               (gpointer) image);
  3244.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  3245.   gtk_widget_show (button);
  3246.  
  3247.   /*  Fill with the selected gradient  */
  3248.   palette_import_fill_grad_preview
  3249.     (image, gimp_context_get_gradient (gimp_context_get_user ()));
  3250.   import_dialog->import_type = GRAD_IMPORT;
  3251.   gtk_signal_connect (GTK_OBJECT (gimp_context_get_user ()), "gradient_changed",
  3252.               GTK_SIGNAL_FUNC (palette_import_gradient_update),
  3253.               NULL);
  3254.  
  3255.   /*  keep the dialog up-to-date  */
  3256.   gtk_signal_connect (GTK_OBJECT (image_context), "add",
  3257.               GTK_SIGNAL_FUNC (palette_import_image_new),
  3258.               NULL);
  3259.   gtk_signal_connect (GTK_OBJECT (image_context), "remove",
  3260.               GTK_SIGNAL_FUNC (palette_import_image_destroyed),
  3261.               NULL);
  3262.  
  3263.   return import_dialog;
  3264. }
  3265.