home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / gimpbrushlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  11.3 KB  |  470 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. #include <ctype.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #ifdef HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #ifdef HAVE_DIRENT_H
  31. #include <dirent.h>
  32. #endif
  33. #include <math.h>
  34.  
  35. #include <glib.h>
  36.  
  37. #include "apptypes.h"
  38.  
  39. #include "appenv.h"
  40. #include "gimpbrushgenerated.h"
  41. #include "gimpbrushpipe.h"
  42. #include "brush_header.h"
  43. #include "brush_select.h"
  44. #include "datafiles.h"
  45. #include "gimprc.h"
  46. #include "gimpsignal.h"
  47. #include "gimplist.h"
  48. #include "gimpbrush.h"
  49. #include "gimpbrushlist.h"
  50.  
  51. #include "libgimp/gimpenv.h"
  52.  
  53. #include "libgimp/gimpintl.h"
  54.  
  55.  
  56. /*  global variables  */
  57. GimpBrushList *brush_list = NULL;
  58.  
  59.  
  60. /*  local function prototypes  */
  61. static void   brushes_brush_load (gchar         *filename);
  62.  
  63. static gint   brush_compare_func (gconstpointer  first,
  64.                   gconstpointer  second);
  65.  
  66.  
  67. /*  class functions  */
  68. static GimpObjectClass* parent_class = NULL;
  69.  
  70.  
  71. static void
  72. gimp_brush_list_add_func (GimpList *list,
  73.               gpointer  val)
  74. {
  75.   list->list = g_slist_insert_sorted (list->list, val, brush_compare_func);
  76.   GIMP_BRUSH_LIST (list)->num_brushes++;
  77. }
  78.  
  79. static void
  80. gimp_brush_list_remove_func (GimpList *list,
  81.                  gpointer  val)
  82. {
  83.   list->list = g_slist_remove (list->list, val);
  84.  
  85.   GIMP_BRUSH_LIST (list)->num_brushes--;
  86. }
  87.  
  88. static void
  89. gimp_brush_list_class_init (GimpBrushListClass *klass)
  90. {
  91.   GimpListClass *gimp_list_class;
  92.   
  93.   gimp_list_class = GIMP_LIST_CLASS (klass);
  94.   gimp_list_class->add    = gimp_brush_list_add_func;
  95.   gimp_list_class->remove = gimp_brush_list_remove_func;
  96.  
  97.   parent_class = gtk_type_class (gimp_list_get_type ());
  98. }
  99.  
  100. void
  101. gimp_brush_list_init (GimpBrushList *list)
  102. {
  103.   list->num_brushes = 0;
  104. }
  105.  
  106. GtkType
  107. gimp_brush_list_get_type (void)
  108. {
  109.   static GtkType type = 0;
  110.  
  111.   if (!type)
  112.     {
  113.       GtkTypeInfo info =
  114.       {
  115.     "GimpBrushList",
  116.     sizeof (GimpBrushList),
  117.     sizeof (GimpBrushListClass),
  118.     (GtkClassInitFunc) gimp_brush_list_class_init,
  119.     (GtkObjectInitFunc) gimp_brush_list_init,
  120.     /* reserved_1 */ NULL,
  121.     /* reserved_2 */ NULL,
  122.     (GtkClassInitFunc) NULL
  123.       };
  124.  
  125.       type = gtk_type_unique (gimp_list_get_type (), &info);
  126.     }
  127.  
  128.   return type;
  129. }
  130.  
  131. GimpBrushList *
  132. gimp_brush_list_new (void)
  133. {
  134.   GimpBrushList *list;
  135.  
  136.   list = GIMP_BRUSH_LIST (gtk_type_new (gimp_brush_list_get_type ()));
  137.  
  138.   GIMP_LIST (list)->type = GIMP_TYPE_BRUSH;
  139.   GIMP_LIST (list)->weak = FALSE;
  140.  
  141.   return list;
  142. }
  143.  
  144. /*  function declarations  */
  145. void
  146. brushes_init (gboolean no_data)
  147. {
  148.   if (brush_list)
  149.     brushes_free ();
  150.   else
  151.     brush_list = gimp_brush_list_new ();
  152.  
  153.   if (brush_path != NULL && !no_data)
  154.     {
  155.       brush_select_freeze_all ();
  156.  
  157.       datafiles_read_directories (brush_path, brushes_brush_load, 0);
  158.       datafiles_read_directories (brush_vbr_path, brushes_brush_load, 0);
  159.  
  160.       brush_select_thaw_all ();
  161.     }
  162.  
  163.   gimp_context_refresh_brushes ();
  164. }
  165.  
  166. GimpBrush *
  167. brushes_get_standard_brush (void)
  168. {
  169.   static GimpBrush *standard_brush = NULL;
  170.  
  171.   if (! standard_brush)
  172.     {
  173.       standard_brush =
  174.     GIMP_BRUSH (gimp_brush_generated_new (5.0, 0.5, 0.0, 1.0));
  175.  
  176.       gimp_brush_set_name (standard_brush, "Standard");
  177.  
  178.       /*  set ref_count to 2 --> never swap the standard brush  */
  179.       gtk_object_ref (GTK_OBJECT (standard_brush));
  180.       gtk_object_ref (GTK_OBJECT (standard_brush));
  181.       gtk_object_sink (GTK_OBJECT (standard_brush));
  182.     }
  183.  
  184.   return standard_brush;
  185. }
  186.  
  187. static void
  188. brushes_brush_load (gchar *filename)
  189. {
  190.   GimpBrush *brush;
  191.  
  192.   if (strcmp (&filename[strlen (filename) - 4], ".gbr") == 0 ||
  193.       strcmp (&filename[strlen (filename) - 4], ".gpb") == 0)
  194.     {
  195.       brush = gimp_brush_load (filename);
  196.  
  197.       if (brush != NULL)
  198.     gimp_brush_list_add (brush_list, brush);
  199.       else
  200.     g_message (_("Warning: Failed to load brush\n\"%s\""), filename);
  201.     }
  202.   else if (strcmp (&filename[strlen(filename) - 4], ".vbr") == 0)
  203.     {
  204.       brush = gimp_brush_generated_load (filename);
  205.  
  206.       if (brush != NULL)
  207.     gimp_brush_list_add (brush_list, GIMP_BRUSH (brush));
  208.       else
  209.     g_message (_("Warning: Failed to load brush\n\"%s\""), filename);
  210.     }
  211.   else if (strcmp (&filename[strlen (filename) - 4], ".gih") == 0)
  212.     {
  213.       brush = gimp_brush_pipe_load (filename);
  214.  
  215.       if (brush != NULL)
  216.     gimp_brush_list_add (brush_list, GIMP_BRUSH (brush));
  217.       else
  218.     g_message (_("Warning: Failed to load brush pipe\n\"%s\""), filename);
  219.     }
  220. }
  221.  
  222. static gint
  223. brush_compare_func (gconstpointer first,
  224.             gconstpointer second)
  225. {
  226.   return strcmp (((const GimpBrush *) first)->name, 
  227.          ((const GimpBrush *) second)->name);
  228. }
  229.  
  230. void
  231. brushes_free (void)
  232. {
  233.   GList *vbr_path;
  234.   gchar *vbr_dir;
  235.  
  236.   if (!brush_list)
  237.     return;
  238.  
  239.   vbr_path = gimp_path_parse (brush_vbr_path, 16, TRUE, NULL);
  240.   vbr_dir  = gimp_path_get_user_writable_dir (vbr_path);
  241.   gimp_path_free (vbr_path);
  242.  
  243.   brush_select_freeze_all ();
  244.  
  245.   while (GIMP_LIST (brush_list)->list)
  246.     {
  247.       GimpBrush *brush = GIMP_BRUSH (GIMP_LIST (brush_list)->list->data);
  248.  
  249.       if (GIMP_IS_BRUSH_GENERATED (brush) && vbr_dir)
  250.     {
  251.       gchar *filename = NULL;
  252.       if (!brush->filename)
  253.         {
  254.           FILE *tmp_fp;
  255.           gint  unum = 0;
  256.  
  257.           if (vbr_dir)
  258.             {
  259.           char *safe_name;
  260.           int i;
  261.           /* make sure we don't create a naughty filename */
  262.           safe_name = g_strdup(brush->name);
  263.           if (safe_name[0] == '.')
  264.             safe_name[0] = '_';
  265.           for (i = 0; safe_name[i]; i++)
  266.             if (safe_name[i] == G_DIR_SEPARATOR || isspace(safe_name[i]))
  267.               safe_name[i] = '_';
  268.  
  269.           filename = g_strdup_printf ("%s%s.vbr",
  270.                           vbr_dir,
  271.                           safe_name);
  272.           while ((tmp_fp = fopen (filename, "r")))
  273.           { /* make sure we don't overite an existing brush */
  274.             fclose (tmp_fp);
  275.             g_free (filename);
  276.             filename = g_strdup_printf ("%s%s_%d.vbr", 
  277.                         vbr_dir, safe_name, unum);
  278.             unum++;
  279.           }
  280.           g_free (safe_name);
  281.         }
  282.         }
  283.       else
  284.         {
  285.           filename = g_strdup (brush->filename);
  286.           if (strlen(filename) < 4 || strcmp (&filename[strlen (filename) - 4],
  287.                           ".vbr"))
  288.             { /* we only want to save .vbr files, so set filename to null
  289.              if this isn't a .vbr file */
  290.           g_free (filename);
  291.           filename = NULL;
  292.         }
  293.         }
  294.       /*  we are (finaly) ready to try to save the generated brush file  */
  295.       if (filename)
  296.         {
  297.           gimp_brush_generated_save (GIMP_BRUSH_GENERATED (brush),
  298.                      filename);
  299.           g_free (filename);
  300.         }
  301.     }
  302.  
  303.       gimp_brush_list_remove (brush_list, brush);
  304.     }
  305.  
  306.   brush_select_thaw_all ();
  307.  
  308.   g_free (vbr_dir);
  309. }
  310.  
  311. #if 0
  312. static GSList *
  313. insert_brush_in_list (GSList    *list,
  314.               GimpBrush *brush)
  315. {
  316.   return g_slist_insert_sorted (list, brush, brush_compare_func);
  317. }
  318. #endif
  319.  
  320. gint
  321. gimp_brush_list_get_brush_index (GimpBrushList *brush_list,
  322.                  GimpBrush     *brush)
  323. {
  324.   /* FIXME: make a gimp_list function that does this? */
  325.   return g_slist_index (GIMP_LIST (brush_list)->list, brush);
  326. }
  327.  
  328. GimpBrush *
  329. gimp_brush_list_get_brush_by_index (GimpBrushList *brush_list,
  330.                     gint           index)
  331. {
  332.   GimpBrush *brush = NULL;
  333.   GSList *list;
  334.  
  335.   /* FIXME: make a gimp_list function that does this? */
  336.   list = g_slist_nth (GIMP_LIST (brush_list)->list, index);
  337.   if (list)
  338.     brush = (GimpBrush *) list->data;
  339.  
  340.   return brush;
  341. }
  342.  
  343. static void
  344. gimp_brush_list_uniquefy_brush_name (GimpBrushList *brush_list,
  345.                      GimpBrush     *brush)
  346. {
  347.   GSList    *list;
  348.   GSList    *listb;
  349.   GimpBrush *brushb;
  350.   gint       number = 1;
  351.   gchar     *newname;
  352.   gchar     *oldname;
  353.   gchar     *ext;
  354.  
  355.   g_return_if_fail (GIMP_IS_BRUSH_LIST (brush_list));
  356.   g_return_if_fail (GIMP_IS_BRUSH (brush));
  357.  
  358.   for (list = GIMP_LIST (brush_list)->list; list; list = g_slist_next (list))
  359.     {
  360.       brushb = GIMP_BRUSH (list->data);
  361.  
  362.       if (brush != brushb &&
  363.       strcmp (gimp_brush_get_name (brush),
  364.           gimp_brush_get_name (brushb)) == 0)
  365.     {
  366.       /* names conflict */
  367.       oldname = gimp_brush_get_name (brush);
  368.       newname = g_malloc (strlen (oldname) + 10); /* if this aint enough 
  369.                              yer screwed */
  370.       strcpy (newname, oldname);
  371.       if ((ext = strrchr (newname, '#')))
  372.         {
  373.           number = atoi (ext + 1);
  374.  
  375.           if (&ext[(gint)(log10 (number) + 1)] !=
  376.           &newname[strlen (newname) - 1])
  377.         {
  378.           number = 1;
  379.           ext = &newname[strlen (newname)];
  380.         }
  381.         }
  382.       else
  383.         {
  384.           number = 1;
  385.           ext = &newname[strlen (newname)];
  386.         }
  387.       sprintf (ext, "#%d", number + 1);
  388.       for (listb = GIMP_LIST (brush_list)->list; listb; listb = listb->next)
  389.         {
  390.           brushb = GIMP_BRUSH (listb->data);
  391.  
  392.           if (brush != brushb &&
  393.           strcmp (newname, gimp_brush_get_name (brushb)) == 0)
  394.         {
  395.           number++;
  396.           sprintf (ext, "#%d", number+1);
  397.           listb = GIMP_LIST (brush_list)->list;
  398.         }
  399.         }
  400.       gimp_brush_set_name (brush, newname);
  401.       g_free (newname);
  402.       if (gimp_list_have (GIMP_LIST (brush_list), brush))
  403.         {
  404.           /* ought to have a better way than this to resort the brush */
  405.           gtk_object_ref (GTK_OBJECT (brush));
  406.           gimp_brush_list_remove (brush_list, brush);
  407.           gimp_brush_list_add (brush_list, brush);
  408.           gtk_object_unref (GTK_OBJECT (brush));
  409.         }
  410.       return;
  411.     }
  412.     }
  413. }
  414.  
  415. static void
  416. brush_renamed (GimpBrush     *brush,
  417.            GimpBrushList *brush_list)
  418. {
  419.   gimp_brush_list_uniquefy_brush_name (brush_list, brush);
  420. }
  421.  
  422. void
  423. gimp_brush_list_add (GimpBrushList *brush_list,
  424.              GimpBrush     *brush)
  425. {
  426.   gimp_brush_list_uniquefy_brush_name (brush_list, brush);
  427.   gimp_list_add (GIMP_LIST (brush_list), brush);
  428.   gtk_signal_connect (GTK_OBJECT (brush), "rename",
  429.               GTK_SIGNAL_FUNC (brush_renamed),
  430.               brush_list);
  431. }
  432.  
  433. void
  434. gimp_brush_list_remove (GimpBrushList *brush_list,
  435.             GimpBrush     *brush)
  436. {
  437.   gtk_signal_disconnect_by_data (GTK_OBJECT (brush), brush_list);
  438.  
  439.   gimp_list_remove (GIMP_LIST (brush_list), brush);
  440. }
  441.  
  442. gint
  443. gimp_brush_list_length (GimpBrushList *brush_list)
  444. {
  445.   g_return_val_if_fail (GIMP_IS_BRUSH_LIST (brush_list), 0);
  446.  
  447.   return brush_list->num_brushes;
  448. }
  449.  
  450. GimpBrush *
  451. gimp_brush_list_get_brush (GimpBrushList *blist,
  452.                gchar         *name)
  453. {
  454.   GimpBrush *brushp;
  455.   GSList *list;
  456.  
  457.   if (blist == NULL)
  458.     return NULL;
  459.  
  460.   for (list = GIMP_LIST (brush_list)->list; list; list = g_slist_next (list))
  461.     {
  462.       brushp = (GimpBrush *) list->data;
  463.  
  464.       if (!strcmp (brushp->name, name))
  465.     return brushp;
  466.     }
  467.  
  468.   return NULL;
  469. }
  470.