Hello,

I fixed and improved a few thing in the IFS Compose plugin.
I know I should use bugzilla. The reasons I write here are:
The existing bugreports are 1.2, while I fixed it in 1.3
(except #82472 fix, which I also backported to 1.2), I'm not
sure how to handle this. Some issues were just side effects
of an underlying real problem (#82466, #82473). Bug #82470
I fixed as a side effect of a larger change. The other
things are not in bugzilla at all (like Save/Load), I don't
have separate patches for them, and don't like the
perspective of creating a dozen of individual reports and
separating the patches only for the sake of bugzillization
of the whole thing.

Please critize/check/apply the attached patch (against
1.3.11) and tell me what to do with:

nor #82472 Flip button doesn't act on all selected objects
    (I attached the backport to this one)
min #82466 Toggling between Simple/Full in IfsCompose changes preview
min #82473 IfsCompose disable Undo/Redo button when nothing to be undo
enh #82470 IfsCompose filter: location of 'New' and 'Delete' button not...

and what to do generally in situations like this.

IFS Compose changes:
* implemented Save and Load
* made Flip to act on all selected transformations, fixes #82472
* moved New/Delete from action area below other buttons, fixes #82470
* fixed Delete to be insensitive when num of transforms == 2
* Undo/Redo made insensitive when there's nothing to update, and avoided
  creation of bogus undo levels during color updates, fixes #82466, #82473,
  and other queer undo/redo behaviour
* set alpha of all colors to 1.0 -- ifscompose ignores alpha anyway, and
  default value (122???) makes the color selection dialog pretty confusing
* made Undo, Redo, Select All, Recompute Center menu items visible as buttons,
  so people who don't try right clicking in the design area know about them
* changed confusing numeric frame title to "Transformation n"
* changed the button layout to two centered groups (it looked approximately
  this way before too, but probably only incidentally)

Thanks in advance,

Yeti


--- gimp-1.3.11.orig/plug-ins/ifscompose/ifscompose.c   2002-12-03 20:42:41.000000000 
+0100
+++ gimp-1.3.11/plug-ins/ifscompose/ifscompose.c        2003-02-01 23:25:34.000000000 
++0100
@@ -169,6 +169,12 @@
   GtkWidget *stretch_button;
   gint       stretch_handler;
 
+  GtkWidget *undo_button;
+  GtkWidget *undo_menu_item;
+  GtkWidget *redo_button;
+  GtkWidget *redo_menu_item;
+  GtkWidget *delete_button;
+
   GtkWidget *preview;
   guchar    *preview_data;
   gint       preview_iterations;
@@ -278,6 +284,10 @@
                                           gpointer   data);
 static void ifs_compose_delete_callback   (GtkWidget *widget,
                                           gpointer   data);
+static void ifs_compose_load_callback (GtkWidget *widget,
+                                          gpointer   data);
+static void ifs_compose_save_callback (GtkWidget *widget,
+                                          gpointer   data);
 
 static void ifs_compose_ok_callback       (GtkWidget *widget,
                                           GtkWidget *window);
@@ -300,6 +310,8 @@
 static gint     undo_num = 0;
 static gint     undo_start = 0;
 
+static gchar ifsfile_path[PATH_MAX] = { '\0' };
+
 /* num_elements = 0, signals not inited */
 static IfsComposeVals ifsvals =
 {
@@ -387,8 +399,6 @@
 
   INIT_I18N_UI(); 
 
-  /* kill (getpid(), 19); */
-
   /*  Get the active drawable  */
   active_drawable = gimp_drawable_get (param[2].data.d_drawable);
 
@@ -786,10 +796,10 @@
                         GIMP_STOCK_RESET, ifs_compose_defaults_callback,
                         NULL, NULL, NULL, FALSE, FALSE,
 
-                        GTK_STOCK_DELETE, ifs_compose_delete_callback,
+                        GTK_STOCK_OPEN, ifs_compose_load_callback,
                         NULL, NULL, NULL, FALSE, FALSE,
 
-                        GTK_STOCK_NEW, ifs_compose_new_callback,
+                        GTK_STOCK_SAVE, ifs_compose_save_callback,
                         NULL, NULL, NULL, FALSE, FALSE,
 
                         GTK_STOCK_CANCEL, gtk_widget_destroy,
@@ -850,10 +860,10 @@
 
   /* Iterations and preview options */
 
-  hbox = gtk_hbox_new (FALSE, 4);
+  hbox = gtk_hbox_new (TRUE, 4);
   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
 
-  alignment = gtk_alignment_new (1.0, 0.5, 0.5, 0.0);
+  alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
   gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
 
   util_hbox = gtk_hbox_new (FALSE, 4);
@@ -891,7 +901,7 @@
   gtk_widget_show (alignment);
   gtk_widget_show (util_hbox);
 
-  alignment = gtk_alignment_new (1.0, 0.5, 0.5, 0.0);
+  alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
   gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
 
   util_hbox = gtk_hbox_new (FALSE, 4);
@@ -924,6 +934,70 @@
   gtk_widget_show (alignment);
   gtk_widget_show (hbox);
 
+  /* second util row */
+  hbox = gtk_hbox_new (TRUE, 4);
+  gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
+
+  alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+  gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
+
+  util_hbox = gtk_hbox_new (FALSE, 4);
+  gtk_container_add (GTK_CONTAINER (alignment), util_hbox);
+
+  ifsD->undo_button = gtk_button_new_with_label(_("Undo"));
+  gtk_box_pack_start(GTK_BOX(util_hbox), ifsD->undo_button,
+                    TRUE, TRUE, 0);
+  g_signal_connect(G_OBJECT(ifsD->undo_button), "clicked",
+                   G_CALLBACK(undo), NULL);
+  gtk_widget_set_sensitive(ifsD->undo_button, FALSE);
+  gtk_widget_show(ifsD->undo_button);
+
+  ifsD->redo_button = gtk_button_new_with_label (_("Redo"));
+  gtk_box_pack_start (GTK_BOX (util_hbox), ifsD->redo_button,
+                     TRUE, TRUE, 0);
+  g_signal_connect(G_OBJECT(ifsD->redo_button), "clicked",
+                   G_CALLBACK(redo), NULL);
+  gtk_widget_set_sensitive(ifsD->redo_button, FALSE);
+  gtk_widget_show(ifsD->redo_button);
+
+  button = gtk_button_new_with_label (_("Select All"));
+  gtk_box_pack_start (GTK_BOX (util_hbox), button,
+                     TRUE, TRUE, 0);
+  g_signal_connect(G_OBJECT(button), "clicked",
+                   G_CALLBACK(design_area_select_all_callback), NULL);
+  gtk_widget_show (button);
+
+  gtk_widget_show (alignment);
+  gtk_widget_show (util_hbox);
+
+  alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+  gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
+
+  util_hbox = gtk_hbox_new (FALSE, 4);
+  gtk_container_add (GTK_CONTAINER (alignment), util_hbox);
+
+  ifsD->delete_button = gtk_button_new_with_label (_("Delete"));
+  g_signal_connect(G_OBJECT(ifsD->delete_button), "clicked",
+                   G_CALLBACK(ifs_compose_delete_callback), NULL);
+  gtk_box_pack_start(GTK_BOX(util_hbox), ifsD->delete_button, TRUE, TRUE, 0);
+  gtk_widget_show(ifsD->delete_button);
+
+  button = gtk_button_new_with_label(_("New"));
+  g_signal_connect(G_OBJECT(button), "clicked",
+                   G_CALLBACK(ifs_compose_new_callback), NULL);
+  gtk_box_pack_start (GTK_BOX (util_hbox), button, TRUE, TRUE, 0);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label (_("Recompute center"));
+  gtk_box_pack_start (GTK_BOX (util_hbox), button, TRUE, TRUE, 0);
+  g_signal_connect(G_OBJECT(button), "clicked",
+                   G_CALLBACK(recompute_center_cb), NULL);
+  gtk_widget_show (button);
+
+  gtk_widget_show (util_hbox);
+  gtk_widget_show (alignment);
+  gtk_widget_show (hbox);
+
   /* The current transformation frame */
 
   ifsD->current_frame = gtk_frame_new (NULL);
@@ -1190,25 +1264,29 @@
                             'R', GDK_MOD1_MASK,
                             GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
 
-  menu_item = gtk_menu_item_new_with_label (_("Undo"));
-  gtk_menu_shell_append (GTK_MENU_SHELL (ifsDesign->op_menu), menu_item);
-  gtk_widget_show (menu_item);
-  g_signal_connect (G_OBJECT (menu_item), "activate",
-                   G_CALLBACK (undo),
-                   NULL);
-  gtk_widget_add_accelerator (menu_item,
+  ifsD->undo_menu_item = gtk_menu_item_new_with_label(_("Undo"));
+  gtk_menu_shell_append(GTK_MENU_SHELL(ifsDesign->op_menu),
+                        ifsD->undo_menu_item);
+  gtk_widget_set_sensitive(ifsD->undo_menu_item, FALSE);
+  gtk_widget_show(ifsD->undo_menu_item);
+  g_signal_connect(G_OBJECT(ifsD->undo_menu_item), "activate",
+                  G_CALLBACK(undo),
+                  NULL);
+  gtk_widget_add_accelerator(ifsD->undo_menu_item,
                             "activate",
                             accel_group,
                             'Z', GDK_CONTROL_MASK,
                             GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
 
-  menu_item = gtk_menu_item_new_with_label(_("Redo"));
-  gtk_menu_shell_append (GTK_MENU_SHELL (ifsDesign->op_menu), menu_item);
-  gtk_widget_show(menu_item);
-  g_signal_connect (G_OBJECT (menu_item), "activate",
+  ifsD->redo_menu_item = gtk_menu_item_new_with_label(_("Redo"));
+  gtk_menu_shell_append (GTK_MENU_SHELL (ifsDesign->op_menu),
+                         ifsD->redo_menu_item);
+  gtk_widget_set_sensitive(ifsD->redo_menu_item, FALSE);
+  gtk_widget_show(ifsD->redo_menu_item);
+  g_signal_connect (G_OBJECT (ifsD->redo_menu_item), "activate",
                    G_CALLBACK (redo),
                    NULL);
-  gtk_widget_add_accelerator(menu_item,
+  gtk_widget_add_accelerator(ifsD->redo_menu_item,
                             "activate",
                             accel_group,
                             'R', GDK_CONTROL_MASK,
@@ -1415,7 +1493,7 @@
                  gint btot=0;
                  gint gtot=0;
                  gint mtot=0;
-                 for (jj=0;jj<ifsvals.subdivide;jj++)
+                 for (jj = 0; jj < ifsvals.subdivide; jj++)
                    {
                      ptr = data + 3 *
                        (((j-band_y)*ifsvals.subdivide+jj)*ifsvals.subdivide*width +
@@ -1424,7 +1502,7 @@
                      maskptr = mask +
                        ((j-band_y)*ifsvals.subdivide+jj)*ifsvals.subdivide*width +
                        i*ifsvals.subdivide;
-                     for (ii=0;ii<ifsvals.subdivide;ii++)
+                     for (ii = 0; ii < ifsvals.subdivide; ii++)
                        {
                          maskval = *maskptr++;
                          mtot += maskval;
@@ -1524,9 +1602,13 @@
 static void
 set_current_element (gint index)
 {
+  gchar *frame_name = g_strdup_printf(_("Transformation %s"),
+                                      elements[index]->name);
+
   ifsD->current_element = index;
 
-  gtk_frame_set_label(GTK_FRAME(ifsD->current_frame),elements[index]->name);
+  gtk_frame_set_label(GTK_FRAME(ifsD->current_frame),frame_name);
+  g_free(frame_name);
 
   update_values();
 }
@@ -1564,7 +1646,7 @@
                widget->style->fg_gc[widget->state],
                cx, cy - 10, cx, cy + 10);
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     {
       aff_element_draw(elements[i], element_selected[i],
                       widget->allocation.width,
@@ -1593,10 +1675,10 @@
   gdouble width = widget->allocation.width;
   gdouble height = widget->allocation.height;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     aff_element_compute_trans(elements[i],width,height,
                              ifsvals.center_x, ifsvals.center_y);
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     aff_element_compute_boundary(elements[i],width,height,
                                 elements, ifsvals.num_elements);
 
@@ -1634,7 +1716,7 @@
   ifsD->current_element = -1;
 
   /* Find out where the button press was */
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     {
       if ( ipolygon_contains(elements[i]->click_boundary,event->x,event->y) )
        {
@@ -1652,7 +1734,7 @@
       && ( (ifsD->current_element<0)
           || !element_selected[ifsD->current_element] ))
     {
-      for (i=0;i<ifsvals.num_elements;i++)
+      for (i = 0; i < ifsvals.num_elements; i++)
        element_selected[i] = 0;
     }
 
@@ -1665,7 +1747,7 @@
       ifsDesign->num_selected = 0;
       ifsDesign->op_xcenter = 0.0;
       ifsDesign->op_ycenter = 0.0;
-      for (i=0;i<ifsvals.num_elements;i++)
+      for (i = 0; i < ifsvals.num_elements; i++)
        {
          if (element_selected[i])
            {
@@ -1772,7 +1854,7 @@
       }
     }
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     if (element_selected[i])
       {
        if (ifsDesign->num_selected == ifsvals.num_elements)
@@ -1784,7 +1866,7 @@
 
            cx = ifsDesign->op_center_x * width;
            cy = ifsDesign->op_center_y * width;
-           aff2_apply(&trans,cx,cy,&cx,&cy);
+           aff2_apply(&trans, cx, cy, &cx, &cy);
            ifsvals.center_x = cx / width;
            ifsvals.center_y = cy / width;
          }
@@ -1843,9 +1925,9 @@
   new_index = (undo_start+undo_cur)%UNDO_LEVELS;
 
   /* remove any redo elements or the oldest element if necessary */
-  for (j=new_index;to_delete>0;j=(j+1)%UNDO_LEVELS,to_delete--)
+  for (j = new_index; to_delete > 0; j = (j+1)%UNDO_LEVELS, to_delete--)
     {
-      for (i=0;i<undo_ring[j].ifsvals.num_elements;i++)
+      for (i = 0; i < undo_ring[j].ifsvals.num_elements; i++)
        if (undo_ring[j].elements[i])
          aff_element_free(undo_ring[j].elements[i]);
       g_free(undo_ring[j].elements);
@@ -1857,11 +1939,16 @@
   undo_ring[new_index].element_selected = g_new(gint,ifsvals.num_elements);
   undo_ring[new_index].current_element = ifsD->current_element;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     {
       undo_ring[new_index].elements[i] = NULL;
       undo_ring[new_index].element_selected[i] = element_selected[i];
     }
+
+  gtk_widget_set_sensitive(ifsD->undo_button, undo_cur >= 0);
+  gtk_widget_set_sensitive(ifsD->undo_menu_item, undo_cur >= 0);
+  gtk_widget_set_sensitive(ifsD->redo_button, undo_cur != undo_num-1);
+  gtk_widget_set_sensitive(ifsD->redo_menu_item, undo_cur != undo_num-1);
 }
 
 static void
@@ -1910,7 +1997,7 @@
   undo_ring[el].current_element = tcurrent;
 
   /* now swap back any unchanged elements */
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     if (!elements[i])
       {
        elements[i] = undo_ring[el].elements[i];
@@ -1936,6 +2023,11 @@
       undo_exchange((undo_start+undo_cur)%UNDO_LEVELS);
       undo_cur--;
     }
+
+  gtk_widget_set_sensitive(ifsD->undo_button, undo_cur >= 0);
+  gtk_widget_set_sensitive(ifsD->undo_menu_item, undo_cur >= 0);
+  gtk_widget_set_sensitive(ifsD->redo_button, undo_cur != undo_num-1);
+  gtk_widget_set_sensitive(ifsD->redo_menu_item, undo_cur != undo_num-1);
 }
 
 static void
@@ -1946,6 +2038,11 @@
       undo_cur++;
       undo_exchange((undo_start+undo_cur)%UNDO_LEVELS);
     }
+
+  gtk_widget_set_sensitive(ifsD->undo_button, undo_cur >= 0);
+  gtk_widget_set_sensitive(ifsD->undo_menu_item, undo_cur >= 0);
+  gtk_widget_set_sensitive(ifsD->redo_button, undo_cur != undo_num-1);
+  gtk_widget_set_sensitive(ifsD->redo_menu_item, undo_cur != undo_num-1);
 }
 
 static void
@@ -1954,7 +2051,7 @@
 {
   gint i;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     element_selected[i] = TRUE;
 
   design_area_redraw();
@@ -2002,6 +2099,7 @@
 
   ColorMap *color_map = g_new (ColorMap,1);
 
+  gimp_rgb_set_alpha(data, 1.0);
   color_map->color       = data;
   color_map->fixed_point = fixed_point;
   color_map->hbox        = gtk_hbox_new (FALSE,2);
@@ -2048,6 +2146,9 @@
 color_map_color_changed_cb (GtkWidget *widget,
                            ColorMap  *color_map)
 {
+  if (ifsD->in_update)
+    return;
+
   undo_begin ();
   undo_update (ifsD->current_element);
  
@@ -2065,11 +2166,11 @@
 color_map_update (ColorMap *color_map)
 {
   gimp_color_button_set_color (GIMP_COLOR_BUTTON (color_map->button),
-                              color_map->color);
+                               color_map->color);
 
   if (color_map->fixed_point)
     gimp_color_area_set_color (GIMP_COLOR_AREA (color_map->orig_preview), 
-                              color_map->color);
+                               color_map->color);
 }
 
 static void
@@ -2097,10 +2198,9 @@
   cur->v.simple_color = GTK_TOGGLE_BUTTON(widget)->active;
   ifsD->current_vals.simple_color = cur->v.simple_color;
   if (cur->v.simple_color)
-    {
-      aff_element_compute_color_trans(cur);
-      val_changed_update();
-    }
+    aff_element_compute_color_trans(cur);
+
+  val_changed_update();
   simple_color_set_sensitive();
 }
 
@@ -2364,7 +2464,7 @@
   if (save_undo)
     undo_begin();
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     {
       if (save_undo)
        undo_update(i);
@@ -2378,7 +2478,7 @@
   ifsvals.center_x = center_x/ifsvals.num_elements;
   ifsvals.center_y = center_y/ifsvals.num_elements;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     {
        aff_element_decompose_trans(elements[i],&elements[i]->trans,
                                    1,ifsvals.aspect_ratio,
@@ -2387,7 +2487,7 @@
 
   if (width > 1 && height > 1)
     {
-      for (i=0;i<ifsvals.num_elements;i++)
+      for (i = 0; i < ifsvals.num_elements; i++)
        aff_element_compute_trans(elements[i],width,height,
                                  ifsvals.center_x, ifsvals.center_y);
       design_area_redraw();
@@ -2414,8 +2514,29 @@
 flip_check_button_callback (GtkWidget *widget,
                            gpointer   data)
 {
-  ifsD->current_vals.flip = GTK_TOGGLE_BUTTON(widget)->active;
-  val_changed_update ();
+  guint i;
+  gdouble width = ifsDesign->area->allocation.width;
+  gdouble height = ifsDesign->area->allocation.height;
+  gint active = GTK_TOGGLE_BUTTON(widget)->active;
+
+  if (ifsD->in_update)
+    return;
+
+  undo_begin();
+  for (i = 0; i < ifsvals.num_elements; i++) {
+    if (element_selected[i]) {
+      undo_update(i);
+      elements[i]->v.flip = active;
+      aff_element_compute_trans(elements[i], width, height,
+                                ifsvals.center_x, ifsvals.center_y);
+    }
+  }
+
+  update_values();
+  design_area_redraw();
+
+  if (ifsD->auto_preview)
+    ifs_compose_preview();
 }
 
 static void
@@ -2428,7 +2549,7 @@
 
   ifsvals.aspect_ratio = (gdouble)ifsD->drawable_height/ifsD->drawable_width;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     aff_element_free(elements[i]);
   count_for_naming = 0;
 
@@ -2497,6 +2618,191 @@
   design_area_redraw ();
 }
 
+/* show a modal dialog */
+void
+yeti_message_dialog(GtkMessageType type, GtkWindow *parent,
+                    gchar *title, gchar *message)
+{
+  GtkWidget *dlg;
+
+  dlg = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL,
+                               type, GTK_BUTTONS_OK, message);
+  if (title)
+    gtk_window_set_title(GTK_WINDOW(dlg), title);
+  gtk_window_set_wmclass(GTK_WINDOW(dlg), "message", "Gimp");
+  gtk_dialog_run(GTK_DIALOG(dlg));
+  gtk_widget_destroy(dlg);
+}
+
+/* save an ifs file */
+static void
+ifsfile_save(GtkWidget *widget, GtkWidget *file_select)
+{
+  gchar *str = ifsvals_stringify(&ifsvals, elements);
+  FILE *fh;
+  char *warning = NULL;
+
+  strcpy(ifsfile_path,
+         gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_select)));
+  fh = fopen(ifsfile_path, "w");
+  if (fh) {
+    fputs(str, fh);
+    fclose(fh);
+  }
+  else
+    warning = g_strdup_printf(_("Cannot save into file `%s'.\n"
+                                "Check the path and permissions.\n"),
+                              ifsfile_path);
+
+  free(str);
+  if (warning) {
+    yeti_message_dialog(GTK_MESSAGE_ERROR, GTK_WINDOW(file_select),
+                        "Save failed", warning);
+    g_free(warning);
+  }
+  gtk_widget_destroy(file_select);
+}
+
+/* replace ifsvals and elements with specified new values
+ * recompute and update everything necessary */
+static void
+ifsfile_replace_ifsvals(IfsComposeVals *new_ifsvals,
+                        AffElement **new_elements)
+{
+  gdouble width = ifsDesign->area->allocation.width;
+  gdouble height = ifsDesign->area->allocation.height;
+  guint i;
+
+  for (i = 0; i < ifsvals.num_elements; i++)
+    aff_element_free(elements[i]);
+  free(elements);
+
+  ifsvals = *new_ifsvals;
+  elements = new_elements;
+  for (i = 0; i < ifsvals.num_elements; i++) {
+    aff_element_compute_trans(elements[i], width, height,
+                              ifsvals.center_x, ifsvals.center_y);
+    aff_element_compute_color_trans(elements[i]);
+  }
+
+  element_selected = g_realloc(element_selected,
+                                ifsvals.num_elements * sizeof(gint));
+  for (i = 0; i < ifsvals.num_elements; i++)
+    element_selected[i] = FALSE;
+
+  if (ifsOptD) {
+    value_pair_update(ifsOptD->iterations_pair);
+    value_pair_update(ifsOptD->subdivide_pair);
+    value_pair_update(ifsOptD->radius_pair);
+    value_pair_update(ifsOptD->memory_pair);
+  }
+
+  set_current_element(0);
+  element_selected[0] = TRUE;
+  recompute_center(FALSE);
+
+  if (ifsD->selected_orig)
+    g_free(ifsD->selected_orig);
+
+  ifsD->selected_orig = g_new(AffElement, ifsvals.num_elements);
+}
+
+/* load an ifs file */
+static void
+ifsfile_load(GtkWidget *widget, GtkWidget *file_select)
+{
+  FILE *fh;
+  guint size = 4096;
+  guint len, pos;
+  guchar *buffer;
+  AffElement **new_elements;
+  IfsComposeVals new_ifsvals;
+  gchar *warning = NULL;
+
+  buffer = g_new(guchar, size);
+  strcpy(ifsfile_path,
+         gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_select)));
+  fh = fopen(ifsfile_path, "r");
+  if (fh) {
+    pos = 0;
+    while ((len = fread(buffer + pos, 1, size - pos, fh)) == size-pos) {
+      pos = size;
+      size *= 2;
+      buffer = g_realloc(buffer, size);
+    }
+    fclose(fh);
+
+    pos += len;
+    buffer[pos] = '\0';
+    if (ifsvals_parse_string(buffer, &new_ifsvals, &new_elements)) {
+      guint i;
+
+      undo_begin ();
+      for (i = 0; i < ifsvals.num_elements; i++)
+        undo_update(i);
+
+      ifsfile_replace_ifsvals(&new_ifsvals, new_elements);
+
+      if (ifsD->auto_preview)
+        ifs_compose_preview();
+
+      design_area_redraw();
+    }
+    else
+      warning = g_strdup_printf(_("File `%s' doesn't seem to be "
+                                  "an IFS Compose file.\n"), ifsfile_path);
+    g_free(buffer);
+  }
+  else
+    warning = g_strdup_printf(_("Cannot open file `%s'.\n"
+                                "Check the path and permissions.\n"),
+                              ifsfile_path);
+
+  if (warning) {
+    yeti_message_dialog(GTK_MESSAGE_ERROR, GTK_WINDOW(file_select),
+                        _("Load failed"), warning);
+    g_free(warning);
+  }
+
+  gtk_widget_destroy(file_select);
+}
+
+static void
+ifs_compose_save_callback(GtkWidget *widget, gpointer data)
+{
+  GtkWidget *file_select;
+
+  file_select = gtk_file_selection_new(_("Save as IFS file"));
+  gimp_help_connect(file_select, gimp_standard_help_func,
+                    "filters/ifscompose.html");
+  gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_select),
+                                  ifsfile_path);
+  g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
+                    "clicked", G_CALLBACK(ifsfile_save), file_select);
+  g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(file_select)->cancel_button),
+                           "clicked", G_CALLBACK(gtk_widget_destroy),
+                           file_select);
+  gtk_widget_show(file_select);
+}
+
+static void
+ifs_compose_load_callback(GtkWidget *widget, gpointer data)
+{
+  GtkWidget *file_select;
+
+  file_select = gtk_file_selection_new(_("Load IFS file"));
+  gimp_help_connect(file_select, gimp_standard_help_func,
+                    "filters/ifscompose.html");
+  gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_select),
+                                  ifsfile_path);
+  g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
+                    "clicked", G_CALLBACK(ifsfile_load), file_select);
+  g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(file_select)->cancel_button),
+                           "clicked", G_CALLBACK(gtk_widget_destroy),
+                           file_select);
+  gtk_widget_show(file_select);
+}
+
 static void
 ifs_compose_new_callback (GtkWidget *widget,
                          gpointer   data)
@@ -2519,7 +2825,7 @@
   element_selected = g_realloc (element_selected,
                                ifsvals.num_elements * sizeof (gint));
 
-  for (i=0;i<ifsvals.num_elements-1;i++)
+  for (i = 0; i < ifsvals.num_elements-1; i++)
     element_selected[i] = FALSE;
   element_selected[ifsvals.num_elements-1] = TRUE;
 
@@ -2535,6 +2841,9 @@
 
   if (ifsD->auto_preview)
     ifs_compose_preview ();
+
+  if (ifsvals.num_elements > 2)
+    gtk_widget_set_sensitive(ifsD->delete_button, TRUE);
 }
 
 static void
@@ -2543,8 +2852,6 @@
 {
   gint i;
   gint new_current;
-  if (ifsvals.num_elements <= 2)
-    return;
 
   undo_begin();
   undo_update(ifsD->current_element);
@@ -2562,7 +2869,7 @@
 
   ifsvals.num_elements--;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     if (element_selected[i])
       {
        new_current = i;
@@ -2576,6 +2883,9 @@
 
   if (ifsD->auto_preview)
     ifs_compose_preview ();
+
+  if (ifsvals.num_elements == 2)
+    gtk_widget_set_sensitive(ifsD->delete_button, FALSE);
 }
 
 static gint
@@ -2589,7 +2899,7 @@
   if (iterations > ifsD->preview_iterations)
     iterations = ifsD->preview_iterations;
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     aff_element_compute_trans(elements[i], width, height,
                              ifsvals.center_x, ifsvals.center_y);
 
@@ -2597,7 +2907,7 @@
             iterations,&ifsvals,0,height,
             ifsD->preview_data,NULL,NULL,TRUE);
 
-  for (i=0;i<ifsvals.num_elements;i++)
+  for (i = 0; i < ifsvals.num_elements; i++)
     aff_element_compute_trans(elements[i],
                              ifsDesign->area->allocation.width,
                              ifsDesign->area->allocation.height,
@@ -2632,7 +2942,7 @@
   gimp_rgb_get_uchar (&color, &rc, &gc, &bc);
 
   ptr = ifsD->preview_data;
-  for (i=0; i < width * height; i++)
+  for (i = 0; i < width * height; i++)
     {
       *ptr++ = rc;
       *ptr++ = gc;
--- gimp-1.3.11.orig/plug-ins/ifscompose/ifscompose_storage.c   2002-05-14 
01:30:03.000000000 +0200
+++ gimp-1.3.11/plug-ins/ifscompose/ifscompose_storage.c        2003-01-30 
+21:48:53.000000000 +0100
@@ -129,6 +129,8 @@
   if (token != G_TOKEN_RIGHT_CURLY)
     return G_TOKEN_RIGHT_CURLY;
 
+  gimp_rgb_set_alpha(result, 1.0);
+
   return G_TOKEN_NONE;
 }
 
_______________________________________________
Gimp-developer mailing list
[EMAIL PROTECTED]
http://lists.xcf.berkeley.edu/mailman/listinfo/gimp-developer

Reply via email to