home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / FractalExplorer / Dialogs.c next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  57.3 KB  |  1,995 lines

  1. #include "config.h"
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8.  
  9. #include <libgimp/gimpui.h>
  10.  
  11. #include "FractalExplorer.h"
  12. #include "Dialogs.h"
  13. #include "Events.h"
  14.  
  15. #include "logo.h"
  16.  
  17. #include "libgimp/stdplugins-intl.h"
  18.  
  19.  
  20. #ifdef G_OS_WIN32
  21. #  include <io.h>
  22. #  ifndef W_OK
  23. #    define W_OK 2
  24. #  endif
  25. #  ifndef S_ISDIR
  26. #    define S_ISDIR(m) ((m) & _S_IFDIR)
  27. #  endif
  28. #  ifndef S_ISREG
  29. #    define S_ISREG(m) ((m) & _S_IFREG)
  30. #  endif
  31. #endif
  32.  
  33. static gdouble *gradient_samples = NULL;
  34. static gchar   *gradient_name    = NULL;
  35.  
  36. /**********************************************************************
  37.  FORWARD DECLARATIONS
  38.  *********************************************************************/
  39.  
  40. static void explorer_logo_dialog (void);
  41.  
  42. /**********************************************************************
  43.  CALLBACKS
  44.  *********************************************************************/
  45.  
  46. static void
  47. dialog_ok_callback (GtkWidget *widget,
  48.             gpointer   data)
  49. {
  50.   wint.run = TRUE;
  51.  
  52.   gtk_widget_destroy (GTK_WIDGET (data));
  53. }
  54.  
  55. static void
  56. dialog_reset_callback (GtkWidget *widget,
  57.                gpointer   data)
  58. {
  59.   wvals.xmin = standardvals.xmin;
  60.   wvals.xmax = standardvals.xmax;
  61.   wvals.ymin = standardvals.ymin;
  62.   wvals.ymax = standardvals.ymax;
  63.   wvals.iter = standardvals.iter;
  64.   wvals.cx = standardvals.cx;
  65.   wvals.cy = standardvals.cy;
  66.  
  67.   dialog_change_scale ();
  68.   set_cmap_preview ();
  69.   dialog_update_preview ();
  70. }
  71.  
  72. static void
  73. dialog_redraw_callback (GtkWidget *widget,
  74.             gpointer   data)
  75. {
  76.   gint alwaysprev = wvals.alwayspreview;
  77.  
  78.   wvals.alwayspreview = TRUE;
  79.   set_cmap_preview();
  80.   dialog_update_preview();
  81.   wvals.alwayspreview = alwaysprev;
  82. }
  83.  
  84. static void
  85. dialog_undo_zoom_callback (GtkWidget *widget,
  86.                gpointer   data)
  87. {
  88.   if (zoomindex > 1)
  89.     {
  90.       zooms[zoomindex] = wvals;
  91.       zoomindex--;
  92.       wvals = zooms[zoomindex];
  93.       dialog_change_scale ();
  94.       set_cmap_preview ();
  95.       dialog_update_preview ();
  96.     }
  97. }
  98.  
  99. static void
  100. dialog_redo_zoom_callback (GtkWidget *widget,
  101.                gpointer   data)
  102. {
  103.   if (zoomindex < zoommax)
  104.     {
  105.       zoomindex++;
  106.       wvals = zooms[zoomindex];
  107.       dialog_change_scale ();
  108.       set_cmap_preview ();
  109.       dialog_update_preview ();
  110.     }
  111. }
  112.  
  113. static void
  114. dialog_step_in_callback (GtkWidget *widget,
  115.              gpointer   data)
  116. {
  117.   double xdifferenz;
  118.   double ydifferenz;
  119.  
  120.   if (zoomindex < zoommax)
  121.     {
  122.       zooms[zoomindex]=wvals;
  123.       zoomindex++;
  124.     }
  125.  
  126.   xdifferenz = wvals.xmax-wvals.xmin;
  127.   ydifferenz = wvals.ymax-wvals.ymin;
  128.   wvals.xmin += 1.0/6.0*xdifferenz;
  129.   wvals.ymin += 1.0/6.0*ydifferenz;
  130.   wvals.xmax -= 1.0/6.0*xdifferenz;
  131.   wvals.ymax -= 1.0/6.0*ydifferenz;
  132.   zooms[zoomindex] = wvals;
  133.  
  134.   dialog_change_scale ();
  135.   set_cmap_preview ();
  136.   dialog_update_preview ();
  137. }                /* dialog_step_in_callback */
  138.  
  139. static void
  140. dialog_step_out_callback (GtkWidget *widget,
  141.               gpointer   data)
  142. {
  143.   double xdifferenz;
  144.   double ydifferenz;
  145.  
  146.   if (zoomindex < zoommax)
  147.     {
  148.       zooms[zoomindex]=wvals;
  149.       zoomindex++;
  150.     }
  151.  
  152.   xdifferenz = wvals.xmax-wvals.xmin;
  153.   ydifferenz = wvals.ymax-wvals.ymin;
  154.   wvals.xmin -= 1.0/4.0*xdifferenz;
  155.   wvals.ymin -= 1.0/4.0*ydifferenz;
  156.   wvals.xmax += 1.0/4.0*xdifferenz;
  157.   wvals.ymax += 1.0/4.0*ydifferenz;
  158.   zooms[zoomindex] = wvals;
  159.  
  160.   dialog_change_scale ();
  161.   set_cmap_preview ();
  162.   dialog_update_preview ();
  163. }
  164.  
  165. static void
  166. explorer_toggle_update (GtkWidget *widget,
  167.             gpointer   data)
  168. {
  169.   gimp_toggle_button_update (widget, data);
  170.  
  171.   set_cmap_preview ();
  172.   dialog_update_preview ();
  173. }
  174.  
  175. static void
  176. explorer_radio_update  (GtkWidget *widget,
  177.             gpointer   data)
  178. {
  179.   gimp_radio_button_update (widget, data);
  180.  
  181.   set_cmap_preview ();
  182.   dialog_update_preview ();
  183. }
  184.  
  185. static void
  186. explorer_double_adjustment_update (GtkAdjustment *adjustment,
  187.                    gpointer       data)
  188. {
  189.   gimp_double_adjustment_update (adjustment, data);
  190.  
  191.   set_cmap_preview ();
  192.   dialog_update_preview ();
  193. }
  194.  
  195. static void
  196. explorer_number_of_colors_callback (GtkAdjustment *adjustment,
  197.                     gpointer       data)
  198. {
  199.   gint dummy;
  200.  
  201.   gimp_int_adjustment_update (adjustment, data);
  202.  
  203.   g_free (gradient_samples);
  204.  
  205.   if (gradient_name == NULL)
  206.     gradient_name = gimp_gradients_get_active ();
  207.  
  208.   gimp_gradients_get_gradient_data (gradient_name, &dummy, wvals.ncolors,
  209.                    &gradient_samples);
  210.  
  211.   set_cmap_preview ();
  212.   dialog_update_preview ();
  213. }
  214.  
  215. static void
  216. explorer_gradient_select_callback (gchar    *name,
  217.                    gint      width,
  218.                    gdouble  *gradient_data,
  219.                    gint      dialog_closing,
  220.                    gpointer  data)
  221. {
  222.   gint dummy;
  223.  
  224.   g_free (gradient_name);
  225.   g_free (gradient_samples);
  226.  
  227.   gradient_name = g_strdup (name);
  228.  
  229.   gimp_gradients_get_gradient_data (gradient_name, &dummy, wvals.ncolors,
  230.                    &gradient_samples);
  231.  
  232.   if (wvals.colormode == 1)
  233.     {
  234.       set_cmap_preview();
  235.       dialog_update_preview(); 
  236.     }
  237. }
  238.  
  239. /**********************************************************************
  240.  FUNCTION: explorer_dialog
  241.  *********************************************************************/
  242.  
  243. gint
  244. explorer_dialog (void)
  245. {
  246.   GtkWidget *dialog;
  247.   GtkWidget *top_hbox;
  248.   GtkWidget *left_vbox;
  249.   GtkWidget *abox;
  250.   GtkWidget *vbox;
  251.   GtkWidget *hbbox;
  252.   GtkWidget *frame;
  253.   GtkWidget *pframe;
  254.   GtkWidget *toggle;
  255.   GtkWidget *toggle_vbox;
  256.   GtkWidget *toggle_vbox2;
  257.   GtkWidget *toggle_vbox3;
  258.   GtkWidget *notebook;
  259.   GtkWidget *hbox;
  260.   GtkWidget *table;
  261.   GtkWidget *button;
  262.   GtkWidget *gradient;
  263.   GtkWidget *sep;
  264.   gchar   *gradient_name;
  265.   GSList  *group = NULL;
  266.   gint     i;
  267.  
  268.   gimp_ui_init ("fractalexplorer", TRUE);
  269.  
  270.   plug_in_parse_fractalexplorer_path ();
  271.  
  272.   wint.wimage = g_new (guchar, preview_width * preview_height * 3);
  273.   elements    = g_new (DialogElements, 1);
  274.  
  275.   dialog = maindlg =
  276.     gimp_dialog_new ("Fractal Explorer <Daniel Cotting/cotting@multimania.com>",
  277.              "fractalexplorer",
  278.              gimp_standard_help_func, "filters/fractalexplorer.html",
  279.              GTK_WIN_POS_NONE,
  280.              FALSE, TRUE, FALSE,
  281.  
  282.              _("About"), explorer_logo_dialog,
  283.              NULL, NULL, NULL, FALSE, FALSE,
  284.              _("OK"), dialog_ok_callback,
  285.              NULL, NULL, NULL, TRUE, FALSE,
  286.              _("Cancel"), gtk_widget_destroy,
  287.              NULL, 1, NULL, FALSE, TRUE,
  288.  
  289.              NULL);
  290.  
  291.   gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
  292.               GTK_SIGNAL_FUNC (gtk_main_quit),
  293.               NULL);
  294.  
  295.   gimp_help_init ();
  296.  
  297.   top_hbox = gtk_hbox_new (FALSE, 6);
  298.   gtk_container_set_border_width (GTK_CONTAINER (top_hbox), 6);
  299.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_hbox,
  300.               FALSE, FALSE, 0);
  301.   gtk_widget_show (top_hbox);
  302.  
  303.   left_vbox = gtk_vbox_new (FALSE, 6);
  304.   gtk_box_pack_start (GTK_BOX (top_hbox), left_vbox, FALSE, FALSE, 0);
  305.   gtk_widget_show (left_vbox);
  306.  
  307.   /*  Preview  */
  308.   frame = gtk_frame_new (_("Preview"));
  309.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  310.   gtk_box_pack_start (GTK_BOX (left_vbox), frame, FALSE, FALSE, 0);
  311.   gtk_widget_show (frame);
  312.  
  313.   vbox = gtk_vbox_new (FALSE, 4);
  314.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  315.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  316.   gtk_widget_show (vbox);
  317.  
  318.   abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  319.   gtk_box_pack_start (GTK_BOX (vbox), abox, FALSE, FALSE, 0);
  320.   gtk_widget_show (abox);
  321.  
  322.   pframe = gtk_frame_new (NULL);
  323.   gtk_frame_set_shadow_type (GTK_FRAME (pframe), GTK_SHADOW_IN);
  324.   gtk_container_add (GTK_CONTAINER (abox), pframe);
  325.   gtk_widget_show (pframe);
  326.  
  327.   wint.preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  328.   gtk_preview_size (GTK_PREVIEW (wint.preview), preview_width, preview_height);
  329.   gtk_container_add (GTK_CONTAINER (pframe), wint.preview);
  330.   gtk_signal_connect (GTK_OBJECT (wint.preview), "button_press_event",
  331.               (GtkSignalFunc) preview_button_press_event,
  332.               NULL);
  333.   gtk_signal_connect (GTK_OBJECT (wint.preview), "button_release_event",
  334.               (GtkSignalFunc) preview_button_release_event,
  335.               NULL);
  336.   gtk_signal_connect (GTK_OBJECT (wint.preview), "motion_notify_event",
  337.               (GtkSignalFunc) preview_motion_notify_event,
  338.               NULL);
  339.   gtk_signal_connect (GTK_OBJECT (wint.preview), "leave_notify_event",
  340.               (GtkSignalFunc) preview_leave_notify_event,
  341.               NULL);
  342.   gtk_signal_connect (GTK_OBJECT (wint.preview), "enter_notify_event",
  343.               (GtkSignalFunc) preview_enter_notify_event,
  344.               NULL);
  345.   gtk_widget_set_events (wint.preview, (GDK_BUTTON_PRESS_MASK |
  346.                     GDK_BUTTON_RELEASE_MASK |
  347.                     GDK_POINTER_MOTION_MASK |
  348.                     GDK_LEAVE_NOTIFY_MASK |
  349.                     GDK_ENTER_NOTIFY_MASK));
  350.   gtk_widget_show (wint.preview);
  351.  
  352.   toggle = gtk_check_button_new_with_label (_("Realtime Preview"));
  353.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  354.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  355.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  356.               &wvals.alwayspreview);
  357.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.alwayspreview);
  358.   gtk_widget_show (toggle);
  359.   gimp_help_set_help_data (toggle, _("If you enable this option the preview "
  360.                      "will be redrawn automatically"), NULL);
  361.  
  362.   button = gtk_button_new_with_label (_("Redraw"));
  363.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  364.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  365.               GTK_SIGNAL_FUNC (dialog_redraw_callback),
  366.               dialog);
  367.   gtk_widget_show (button);
  368.   gimp_help_set_help_data (button, _("Redraw preview"), NULL);
  369.  
  370.   /*  Zoom Options  */
  371.   frame = gtk_frame_new (_("Zoom Options"));
  372.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  373.   gtk_box_pack_end (GTK_BOX (left_vbox), frame, FALSE, FALSE, 0);
  374.   gtk_widget_show (frame);
  375.  
  376.   vbox = gtk_vbox_new(FALSE, 0);
  377.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  378.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  379.   gtk_widget_show (vbox);
  380.  
  381.   button = gtk_button_new_with_label (_("Undo Zoom"));
  382.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  383.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  384.               GTK_SIGNAL_FUNC (dialog_undo_zoom_callback),
  385.               dialog);
  386.   gtk_widget_show (button);
  387.   gimp_help_set_help_data (button, _("Undo last zoom"), NULL);
  388.  
  389.   button = gtk_button_new_with_label (_("Redo Zoom"));
  390.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  391.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  392.               GTK_SIGNAL_FUNC (dialog_redo_zoom_callback),
  393.               dialog);
  394.   gtk_widget_show (button);
  395.   gimp_help_set_help_data (button, _("Redo last zoom"), NULL);
  396.  
  397.   button = gtk_button_new_with_label (_("Step In"));
  398.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  399.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  400.               GTK_SIGNAL_FUNC (dialog_step_in_callback),
  401.               dialog);
  402.   gtk_widget_show (button);
  403.  
  404.   button = gtk_button_new_with_label (_("Step Out"));
  405.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  406.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  407.               GTK_SIGNAL_FUNC (dialog_step_out_callback),
  408.               dialog);
  409.   gtk_widget_show (button);
  410.  
  411.  
  412.   /*  Create notebook  */
  413.   notebook = gtk_notebook_new ();
  414.   gtk_box_pack_start (GTK_BOX (top_hbox), notebook, FALSE, FALSE, 0);
  415.   gtk_widget_show (notebook);
  416.  
  417.   /*  "Parameters" page  */
  418.   vbox = gtk_vbox_new (FALSE, 4);
  419.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  420.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox,
  421.                 gtk_label_new (_("Parameters")));
  422.   gtk_widget_show (vbox);
  423.  
  424.   frame = gtk_frame_new (_("Fractal Parameters"));
  425.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  426.   gtk_widget_show (frame);
  427.  
  428.   table = gtk_table_new (8, 3, FALSE);
  429.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  430.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  431.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  432.   gtk_table_set_row_spacing (GTK_TABLE (table), 6, 4);
  433.   gtk_container_add (GTK_CONTAINER (frame), table);
  434.   gtk_widget_show (table);
  435.  
  436.   elements->xmin =
  437.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  438.               _("XMIN:"), SCALE_WIDTH, 100,
  439.               wvals.xmin, -3, 3, 0.001, 0.01, 5,
  440.               TRUE, 0, 0,
  441.               _("Change the first (minimal) x-coordinate "
  442.                 "delimitation"), NULL);
  443.   gtk_signal_connect (GTK_OBJECT (elements->xmin), "value_changed",
  444.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  445.               &wvals.xmin);
  446.  
  447.   elements->xmax =
  448.     gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  449.               _("XMAX:"), SCALE_WIDTH, 100,
  450.               wvals.xmax, -3, 3, 0.001, 0.01, 5,
  451.               TRUE, 0, 0,
  452.               _("Change the second (maximal) x-coordinate "
  453.                 "delimitation"), NULL);
  454.   gtk_signal_connect (GTK_OBJECT (elements->xmax), "value_changed",
  455.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  456.               &wvals.xmax);
  457.  
  458.   elements->ymin =
  459.     gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
  460.               _("YMIN:"), SCALE_WIDTH, 100,
  461.               wvals.ymin, -3, 3, 0.001, 0.01, 5,
  462.               TRUE, 0, 0,
  463.               _("Change the first (minimal) y-coordinate "
  464.                 "delimitation"), NULL);
  465.   gtk_signal_connect (GTK_OBJECT (elements->ymin), "value_changed",
  466.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  467.               &wvals.ymin);
  468.  
  469.   elements->ymax =
  470.     gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
  471.               _("YMAX:"), SCALE_WIDTH, 100,
  472.               wvals.ymax, -3, 3, 0.001, 0.01, 5,
  473.               TRUE, 0, 0,
  474.               _("Change the second (maximal) y-coordinate "
  475.                 "delimitation"), NULL);
  476.   gtk_signal_connect (GTK_OBJECT (elements->ymax), "value_changed",
  477.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  478.               &wvals.ymax);
  479.  
  480.   elements->iter =
  481.     gimp_scale_entry_new (GTK_TABLE (table), 0, 4,
  482.               _("ITER:"), SCALE_WIDTH, 100,
  483.               wvals.iter, 0, 1000, 1, 10, 5,
  484.               TRUE, 0, 0,
  485.               _("Change the iteration value. The higher it "
  486.                 "is, the more details will be calculated, "
  487.                 "which will take more time"), NULL);
  488.   gtk_signal_connect (GTK_OBJECT (elements->iter), "value_changed",
  489.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  490.               &wvals.iter);
  491.  
  492.   elements->cx =
  493.     gimp_scale_entry_new (GTK_TABLE (table), 0, 5,
  494.               _("CX:"), SCALE_WIDTH, 100,
  495.               wvals.cx, -2.5, 2.5, 0.001, 0.01, 5,
  496.               TRUE, 0, 0,
  497.               _("Change the CX value (changes aspect of "
  498.                 "fractal, active with every fractal but "
  499.                 "Mandelbrot and Sierpinski)"), NULL);
  500.   gtk_signal_connect (GTK_OBJECT (elements->cx), "value_changed",
  501.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  502.               &wvals.cx);
  503.  
  504.   elements->cy =
  505.     gimp_scale_entry_new (GTK_TABLE (table), 0, 6,
  506.               _("CY:"), SCALE_WIDTH, 100,
  507.               wvals.cy, -2.5, 2.5, 0.001, 0.01, 5,
  508.               TRUE, 0, 0,
  509.               _("Change the CY value (changes aspect of "
  510.                 "fractal, active with every fractal but "
  511.                 "Mandelbrot and Sierpinski)"), NULL);
  512.   gtk_signal_connect (GTK_OBJECT (elements->cy), "value_changed",
  513.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  514.               &wvals.cy);
  515.  
  516.   hbbox = gtk_hbox_new (FALSE, 4);
  517.   gtk_table_attach_defaults (GTK_TABLE (table), hbbox, 0, 3, 7, 8);
  518.   gtk_widget_show (hbbox);
  519.  
  520.   button = gtk_button_new_with_label (_("Load"));
  521.   gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  522.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  523.               GTK_SIGNAL_FUNC (create_load_file_selection),
  524.               dialog);
  525.   gtk_widget_show (button);
  526.   gimp_help_set_help_data (button, _("Load a fractal from file"), NULL);
  527.  
  528.   button = gtk_button_new_with_label (_("Reset"));
  529.   gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  530.   gtk_signal_connect (GTK_OBJECT(button), "clicked",
  531.               GTK_SIGNAL_FUNC (dialog_reset_callback),
  532.               dialog);
  533.   gtk_widget_show (button);
  534.   gimp_help_set_help_data (button, _("Reset parameters to default values"),
  535.                NULL);
  536.  
  537.   button = gtk_button_new_with_label (_("Save"));
  538.   gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  539.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  540.               GTK_SIGNAL_FUNC (create_file_selection),
  541.               dialog);
  542.   gtk_widget_show (button);
  543.   gimp_help_set_help_data (button, _("Save active fractal to file"), NULL);
  544.     
  545.   /*  Fractal type toggle box  */
  546.   frame = gtk_frame_new (_("Fractal Type"));
  547.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  548.  
  549.   hbox = gtk_hbox_new (FALSE, 6);
  550.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  551.   gtk_container_add (GTK_CONTAINER (frame), hbox);
  552.  
  553.   toggle_vbox =
  554.     gimp_radio_group_new2 (FALSE, NULL,
  555.                explorer_radio_update,
  556.                &wvals.fractaltype,
  557.                (gpointer) &wvals.fractaltype,
  558.  
  559.                _("Mandelbrot"), (gpointer) TYPE_MANDELBROT,
  560.                &(elements->type[TYPE_MANDELBROT]),
  561.                _("Julia"), (gpointer) TYPE_JULIA,
  562.                &(elements->type[TYPE_JULIA]),
  563.                _("Barnsley 1"), (gpointer) TYPE_BARNSLEY_1,
  564.                &(elements->type[TYPE_BARNSLEY_1]),
  565.                _("Barnsley 2"), (gpointer) TYPE_BARNSLEY_2,
  566.                &(elements->type[TYPE_BARNSLEY_2]),
  567.                _("Barnsley 3"), (gpointer) TYPE_BARNSLEY_3,
  568.                &(elements->type[TYPE_BARNSLEY_3]),
  569.                _("Spider"), (gpointer) TYPE_SPIDER,
  570.                &(elements->type[TYPE_SPIDER]),
  571.                _("Man'o'war"), (gpointer) TYPE_MAN_O_WAR,
  572.                &(elements->type[TYPE_MAN_O_WAR]),
  573.                _("Lambda"), (gpointer) TYPE_LAMBDA,
  574.                &(elements->type[TYPE_LAMBDA]),
  575.                _("Sierpinski"), (gpointer) TYPE_SIERPINSKI,
  576.                &(elements->type[TYPE_SIERPINSKI]),
  577.  
  578.                NULL);
  579.  
  580.   toggle_vbox2 = gtk_vbox_new (FALSE, 1);
  581.   for (i = TYPE_BARNSLEY_2; i <= TYPE_SPIDER; i++)
  582.     {
  583.       gtk_object_ref (GTK_OBJECT (elements->type[i]));
  584.       gtk_widget_hide (elements->type[i]);
  585.       gtk_container_remove (GTK_CONTAINER (toggle_vbox), elements->type[i]);
  586.       gtk_box_pack_start (GTK_BOX (toggle_vbox2), elements->type[i],
  587.               FALSE, FALSE, 0);
  588.       gtk_widget_show (elements->type[i]);
  589.       gtk_object_unref (GTK_OBJECT (elements->type[i]));
  590.     }
  591.  
  592.   toggle_vbox3 = gtk_vbox_new (FALSE, 1);
  593.   for (i = TYPE_MAN_O_WAR; i <= TYPE_SIERPINSKI; i++)
  594.     {
  595.       gtk_object_ref (GTK_OBJECT (elements->type[i]));
  596.       gtk_widget_hide (elements->type[i]);
  597.       gtk_container_remove (GTK_CONTAINER (toggle_vbox), elements->type[i]);
  598.       gtk_box_pack_start (GTK_BOX (toggle_vbox3), elements->type[i],
  599.               FALSE, FALSE, 0);
  600.       gtk_widget_show (elements->type[i]);
  601.       gtk_object_unref (GTK_OBJECT (elements->type[i]));
  602.     }
  603.  
  604.   gtk_container_set_border_width (GTK_CONTAINER (toggle_vbox), 0);
  605.   gtk_box_pack_start (GTK_BOX (hbox), toggle_vbox, FALSE, FALSE, 0);
  606.   gtk_widget_show (toggle_vbox);
  607.  
  608.   gtk_box_pack_start (GTK_BOX (hbox), toggle_vbox2, FALSE, FALSE, 0);
  609.   gtk_widget_show (toggle_vbox2);
  610.  
  611.   gtk_box_pack_start (GTK_BOX (hbox), toggle_vbox3, FALSE, FALSE, 0);
  612.   gtk_widget_show (toggle_vbox3);
  613.  
  614.   gtk_widget_show (hbox);
  615.   gtk_widget_show (frame);
  616.  
  617.   /*  Color page  */
  618.   vbox = gtk_vbox_new (FALSE, 4);
  619.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  620.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox,
  621.                 gtk_label_new (_("Colors")));
  622.   gtk_widget_show (vbox);
  623.  
  624.   /*  Number of Colors frame  */
  625.   frame = gtk_frame_new (_("Number of Colors"));
  626.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  627.   gtk_widget_show (frame);
  628.  
  629.   table = gtk_table_new (2, 3, FALSE);
  630.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  631.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  632.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  633.   gtk_container_add (GTK_CONTAINER (frame), table);
  634.   gtk_widget_show (table);
  635.  
  636.   elements->ncol =
  637.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  638.               _("Number of Colors:"), SCALE_WIDTH, 0,
  639.               wvals.ncolors, 2, MAXNCOLORS, 1, 10, 0,
  640.               TRUE, 0, 0,
  641.               _("Change the number of colors in the mapping"),
  642.               NULL);
  643.   gtk_signal_connect (GTK_OBJECT (elements->ncol), "value_changed",
  644.               GTK_SIGNAL_FUNC (explorer_number_of_colors_callback),
  645.               &wvals.ncolors);
  646.  
  647.   elements->useloglog = toggle =
  648.     gtk_check_button_new_with_label (_("Use loglog Smoothing"));
  649.   gtk_table_attach_defaults (GTK_TABLE (table), toggle, 0, 3, 1, 2);
  650.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  651.               (GtkSignalFunc) explorer_toggle_update,
  652.               &wvals.useloglog);
  653.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.useloglog);
  654.   gtk_widget_show (toggle);
  655.   gimp_help_set_help_data (toggle, _("Use log log smoothing to eliminate "
  656.                      "\"banding\" in the result"), NULL);
  657.  
  658.   /*  Color Density frame  */
  659.   frame = gtk_frame_new (_("Color Density"));
  660.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  661.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  662.   gtk_widget_show (frame);
  663.  
  664.   table = gtk_table_new (3, 3, FALSE);
  665.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  666.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  667.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  668.   gtk_container_add (GTK_CONTAINER (frame), table);
  669.   gtk_widget_show (table);
  670.  
  671.   elements->red =
  672.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  673.               _("Red:"), SCALE_WIDTH, 0,
  674.               wvals.redstretch, 0, 1, 0.01, 0.1, 2,
  675.               TRUE, 0, 0,
  676.               _("Change the intensity of the red channel"), NULL);
  677.   gtk_signal_connect (GTK_OBJECT (elements->red), "value_changed",
  678.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  679.               &wvals.redstretch);
  680.  
  681.   elements->green =
  682.     gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  683.               _("Green:"), SCALE_WIDTH, 0,
  684.               wvals.greenstretch, 0, 1, 0.01, 0.1, 2,
  685.               TRUE, 0, 0,
  686.               _("Change the intensity of the green channel"), NULL);
  687.   gtk_signal_connect (GTK_OBJECT (elements->green), "value_changed",
  688.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  689.               &wvals.greenstretch);
  690.  
  691.   elements->blue =
  692.     gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
  693.               _("Blue:"), SCALE_WIDTH, 0,
  694.               wvals.bluestretch, 0, 1, 0.01, 0.1, 2,
  695.               TRUE, 0, 0,
  696.               _("Change the intensity of the blue channel"), NULL);
  697.   gtk_signal_connect (GTK_OBJECT (elements->blue), "value_changed",
  698.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  699.               &wvals.bluestretch);
  700.  
  701.   /*  Color Function frame  */
  702.   frame = gtk_frame_new (_("Color Function"));
  703.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  704.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  705.   gtk_widget_show (frame);
  706.  
  707.   hbox = gtk_hbox_new (FALSE, 6);
  708.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  709.   gtk_container_add (GTK_CONTAINER (frame), hbox);
  710.   gtk_widget_show (hbox);
  711.  
  712.   /*  Redmode radio frame  */
  713.   frame = gimp_radio_group_new2 (TRUE, _("Red"),
  714.                  explorer_radio_update,
  715.                  &wvals.redmode, (gpointer) wvals.redmode,
  716.  
  717.                  _("Sine"), (gpointer) SINUS,
  718.                  &elements->redmode[SINUS],
  719.                  _("Cosine"), (gpointer) COSINUS,
  720.                  &elements->redmode[COSINUS],
  721.                  _("None"), (gpointer) NONE,
  722.                  &elements->redmode[NONE],
  723.  
  724.                  NULL);
  725.   gimp_help_set_help_data (elements->redmode[SINUS],
  726.                _("Use sine-function for this color component"),
  727.                NULL);
  728.   gimp_help_set_help_data (elements->redmode[COSINUS],
  729.                _("Use cosine-function for this color "
  730.                  "component"), NULL);
  731.   gimp_help_set_help_data (elements->redmode[NONE],
  732.                _("Use linear mapping instead of any "
  733.                  "trigonometrical function for this color "
  734.                  "channel"), NULL);
  735.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  736.   gtk_widget_show (frame);
  737.  
  738.   toggle_vbox = GTK_BIN (frame)->child;
  739.  
  740.   elements->redinvert = toggle =
  741.     gtk_check_button_new_with_label (_("Inversion"));
  742.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.redinvert);
  743.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  744.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  745.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  746.               &wvals.redinvert);
  747.   gtk_widget_show (toggle);
  748.   gimp_help_set_help_data (toggle,
  749.                _("If you enable this option higher color values "
  750.                  "will be swapped with lower ones and vice "
  751.                  "versa"), NULL);
  752.  
  753.   /*  Greenmode radio frame  */
  754.   frame = gimp_radio_group_new2 (TRUE, _("Green"),
  755.                  explorer_radio_update,
  756.                  &wvals.greenmode, (gpointer) wvals.greenmode,
  757.  
  758.                  _("Sine"), (gpointer) SINUS,
  759.                  &elements->greenmode[SINUS],
  760.                  _("Cosine"), (gpointer) COSINUS,
  761.                  &elements->greenmode[COSINUS],
  762.                  _("None"), (gpointer) NONE,
  763.                  &elements->greenmode[NONE],
  764.  
  765.                  NULL);
  766.   gimp_help_set_help_data (elements->greenmode[SINUS],
  767.                _("Use sine-function for this color component"),
  768.                NULL);
  769.   gimp_help_set_help_data (elements->greenmode[COSINUS],
  770.                _("Use cosine-function for this color "
  771.                  "component"), NULL);
  772.   gimp_help_set_help_data (elements->greenmode[NONE],
  773.                _("Use linear mapping instead of any "
  774.                  "trigonometrical function for this color "
  775.                  "channel"), NULL);
  776.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  777.   gtk_widget_show (frame);
  778.  
  779.   toggle_vbox = GTK_BIN (frame)->child;
  780.  
  781.   elements->greeninvert = toggle =
  782.     gtk_check_button_new_with_label (_("Inversion"));
  783.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.greeninvert);
  784.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  785.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  786.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  787.               &wvals.greeninvert);
  788.   gtk_widget_show (toggle);
  789.   gimp_help_set_help_data (toggle,
  790.                _("If you enable this option higher color values "
  791.                  "will be swapped with lower ones and vice "
  792.                  "versa"), NULL);
  793.  
  794.   /*  Bluemode radio frame  */
  795.   frame = gimp_radio_group_new2 (TRUE, _("Blue"),
  796.                  explorer_radio_update,
  797.                  &wvals.bluemode, (gpointer) wvals.bluemode,
  798.  
  799.                  _("Sine"), (gpointer) SINUS,
  800.                  &elements->bluemode[SINUS],
  801.                  _("Cosine"), (gpointer) COSINUS,
  802.                  &elements->bluemode[COSINUS],
  803.                  _("None"), (gpointer) NONE,
  804.                  &elements->bluemode[NONE],
  805.  
  806.                  NULL);
  807.   gimp_help_set_help_data (elements->bluemode[SINUS],
  808.                _("Use sine-function for this color component"),
  809.                NULL);
  810.   gimp_help_set_help_data (elements->bluemode[COSINUS],
  811.                _("Use cosine-function for this color "
  812.                  "component"), NULL);
  813.   gimp_help_set_help_data (elements->bluemode[NONE],
  814.                _("Use linear mapping instead of any "
  815.                  "trigonometrical function for this color "
  816.                  "channel"), NULL);
  817.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  818.   gtk_widget_show (frame);
  819.  
  820.   toggle_vbox = GTK_BIN (frame)->child;
  821.  
  822.   elements->blueinvert = toggle =
  823.     gtk_check_button_new_with_label (_("Inversion"));
  824.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON( toggle), wvals.blueinvert);
  825.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  826.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  827.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  828.               &wvals.blueinvert);
  829.   gtk_widget_show (toggle);
  830.   gimp_help_set_help_data (toggle,
  831.                _("If you enable this option higher color values "
  832.                  "will be swapped with lower ones and vice "
  833.                  "versa"), NULL);
  834.  
  835.   /*  Colormode toggle box  */
  836.   frame = gtk_frame_new (_("Color Mode"));
  837.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  838.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  839.   gtk_widget_show (frame);
  840.  
  841.   toggle_vbox = gtk_vbox_new (FALSE, 2);
  842.   gtk_container_set_border_width (GTK_CONTAINER (toggle_vbox), 2);
  843.   gtk_container_add (GTK_CONTAINER (frame), toggle_vbox);
  844.   gtk_widget_show (toggle_vbox);
  845.  
  846.   toggle = elements->colormode[0] =
  847.     gtk_radio_button_new_with_label (group, _("As Specified above"));
  848.   group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  849.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  850.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) 0);
  851.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  852.               GTK_SIGNAL_FUNC (explorer_radio_update),
  853.               &wvals.colormode);
  854.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  855.                 wvals.colormode == 0);
  856.   gtk_widget_show (toggle);
  857.   gimp_help_set_help_data (toggle,
  858.                _("Create a color-map with the options you "
  859.                  "specified above (color density/function). The "
  860.                  "result is visible in the preview image"), NULL);
  861.  
  862.   hbox = gtk_hbox_new (FALSE, 6);
  863.   gtk_box_pack_start (GTK_BOX (toggle_vbox), hbox, FALSE, FALSE, 0);
  864.   gtk_widget_show (hbox);
  865.  
  866.   toggle = elements->colormode[1] =
  867.     gtk_radio_button_new_with_label (group,
  868.                      _("Apply Active Gradient to Final Image"));
  869.   group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  870.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
  871.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) 1);
  872.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  873.               GTK_SIGNAL_FUNC (explorer_radio_update),
  874.               &wvals.colormode);
  875.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  876.                 wvals.colormode == 1);
  877.   gtk_widget_show (toggle);
  878.   gimp_help_set_help_data (toggle,
  879.                _("Create a color-map using a gradient from "
  880.                  "the gradient editor"), NULL);
  881.  
  882.   gradient_name = gimp_gradients_get_active ();
  883.   gradient_samples = gimp_gradients_sample_uniform (wvals.ncolors);
  884.   gradient = gimp_gradient_select_widget (_("FractalExplorer Gradient"),
  885.                       gradient_name,
  886.                       explorer_gradient_select_callback,
  887.                       NULL);
  888.   g_free (gradient_name);
  889.   gtk_box_pack_start (GTK_BOX (hbox), gradient, FALSE, FALSE, 0);
  890.   gtk_widget_show (gradient);
  891.  
  892.   sep = gtk_hseparator_new ();
  893.   gtk_box_pack_start (GTK_BOX (toggle_vbox), sep, FALSE, FALSE, 1);
  894.   gtk_widget_show (sep);
  895.  
  896.   abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  897.   {
  898.     gint xsize, ysize;
  899.  
  900.     for (ysize = 1; ysize * ysize * ysize < 8192; ysize++) /**/;
  901.     xsize = wvals.ncolors / ysize;
  902.     while (xsize * ysize < 8192) xsize++;
  903.  
  904.     gtk_widget_set_usize (abox, xsize, ysize * 4);
  905.   }
  906.   gtk_box_pack_start (GTK_BOX (toggle_vbox), abox, FALSE, FALSE, 0);
  907.   gtk_widget_show (abox);
  908.  
  909.   cmap_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  910.   gtk_preview_size (GTK_PREVIEW (cmap_preview), 32, 32);
  911.   gtk_container_add (GTK_CONTAINER (abox), cmap_preview);
  912.   gtk_widget_show (cmap_preview);
  913.  
  914.   frame = add_objects_list ();
  915.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, 
  916.                 gtk_label_new (_("Fractals")));
  917.   gtk_widget_show (frame);
  918.  
  919.   gtk_notebook_set_page (GTK_NOTEBOOK (notebook), 1);
  920.  
  921.   /* Done */
  922.  
  923.   /* Popup for list area: Not yet fully implemented
  924.      fractalexplorer_op_menu_create(maindlg);
  925.   */
  926.  
  927.   gtk_widget_show (dialog);
  928.   ready_now = TRUE;
  929.  
  930.   set_cmap_preview ();
  931.   dialog_update_preview ();
  932.  
  933.   gtk_main ();
  934.   gimp_help_free ();
  935.   gdk_flush ();
  936.  
  937.   if (the_tile != NULL)
  938.     {
  939.       gimp_tile_unref (the_tile, FALSE);
  940.       the_tile = NULL;
  941.     }
  942.  
  943.   g_free (wint.wimage);
  944.  
  945.   return wint.run;
  946. }
  947.  
  948. /**********************************************************************
  949.  FUNCTION: dialog_update_preview
  950.  *********************************************************************/
  951.  
  952. void
  953. dialog_update_preview (void)
  954. {
  955.   gdouble  left;
  956.   gdouble  right;
  957.   gdouble  bottom;
  958.   gdouble  top;
  959.   gdouble  dx;
  960.   gdouble  dy;
  961.   gdouble  cx;
  962.   gdouble  cy;
  963.   gint     px;
  964.   gint     py;
  965.   gint     xcoord;
  966.   gint     ycoord;
  967.   gint     iteration;
  968.   guchar  *p_ul;
  969.   guchar  *p;
  970.   gdouble  a;
  971.   gdouble  b;
  972.   gdouble  x;
  973.   gdouble  y;
  974.   gdouble  oldx;
  975.   gdouble  oldy;
  976.   gdouble  foldxinitx;
  977.   gdouble  foldxinity;
  978.   gdouble  tempsqrx;
  979.   gdouble  tempsqry;
  980.   gdouble  tmpx = 0;
  981.   gdouble  tmpy = 0;
  982.   gdouble  foldyinitx;
  983.   gdouble  foldyinity;
  984.   gdouble  adjust;
  985.   gdouble  xx = 0;
  986.   gint     zaehler;
  987.   gint     color;
  988.   gint     useloglog;
  989.     
  990.   if (NULL == wint.preview)
  991.     return;
  992.  
  993.   if ((ready_now) && (wvals.alwayspreview))
  994.     {
  995.       left = sel_x1;
  996.       right = sel_x2 - 1;
  997.       bottom = sel_y2 - 1;
  998.       top = sel_y1;
  999.       dx = (right - left) / (preview_width - 1);
  1000.       dy = (bottom - top) / (preview_height - 1);
  1001.  
  1002.       xmin = wvals.xmin;
  1003.       xmax = wvals.xmax;
  1004.       ymin = wvals.ymin;
  1005.       ymax = wvals.ymax;
  1006.       cx = wvals.cx;
  1007.       cy = wvals.cy;
  1008.       xbild = preview_width;
  1009.       ybild = preview_height;
  1010.       xdiff = (xmax - xmin) / xbild;
  1011.       ydiff = (ymax - ymin) / ybild;
  1012.  
  1013.       py = 0;
  1014.  
  1015.       p_ul = wint.wimage;
  1016.       iteration = (int) wvals.iter;
  1017.       useloglog = wvals.useloglog;
  1018.       for (ycoord = 0; ycoord < preview_height; ycoord++)
  1019.     {
  1020.       px = 0;
  1021.  
  1022.       for (xcoord = 0; xcoord < preview_width; xcoord++)
  1023.         {
  1024.           a = (double) xmin + (double) xcoord *xdiff;
  1025.           b = (double) ymin + (double) ycoord *ydiff;
  1026.  
  1027.           if (wvals.fractaltype != TYPE_MANDELBROT)
  1028.         {
  1029.           tmpx = x = a;
  1030.           tmpy = y = b;
  1031.         }
  1032.           else
  1033.         {
  1034.           x = 0;
  1035.           y = 0;
  1036.         }
  1037.           for (zaehler = 0;
  1038.            (zaehler < iteration) && ((x * x + y * y) < 4);
  1039.            zaehler++)
  1040.         {
  1041.           oldx = x;
  1042.           oldy = y;
  1043.  
  1044.           switch (wvals.fractaltype)
  1045.             {
  1046.             case TYPE_MANDELBROT:
  1047.               xx = x * x - y * y + a;
  1048.               y = 2.0 * x * y + b;
  1049.               break;
  1050.  
  1051.             case TYPE_JULIA:
  1052.               xx = x * x - y * y + cx;
  1053.               y = 2.0 * x * y + cy; 
  1054.               break;
  1055.  
  1056.             case TYPE_BARNSLEY_1:
  1057.               foldxinitx = oldx * cx;
  1058.               foldyinity = oldy * cy;
  1059.               foldxinity = oldx * cy;
  1060.               foldyinitx = oldy * cx;
  1061.               /* orbit calculation */
  1062.               if (oldx >= 0)
  1063.             {
  1064.                   xx = (foldxinitx - cx - foldyinity);
  1065.                           y  = (foldyinitx - cy + foldxinity);
  1066.             }
  1067.               else
  1068.             {
  1069.                   xx = (foldxinitx + cx - foldyinity);
  1070.                   y  = (foldyinitx + cy + foldxinity);
  1071.             }
  1072.               break;
  1073.  
  1074.             case TYPE_BARNSLEY_2:
  1075.               foldxinitx = oldx * cx;
  1076.               foldyinity = oldy * cy;
  1077.               foldxinity = oldx * cy;
  1078.               foldyinitx = oldy * cx;
  1079.               /* orbit calculation */
  1080.               if (foldxinity + foldyinitx >= 0)
  1081.                         {
  1082.               xx = foldxinitx - cx - foldyinity;
  1083.               y  = foldyinitx - cy + foldxinity;
  1084.                         }
  1085.               else
  1086.                 {
  1087.               xx = foldxinitx + cx - foldyinity;
  1088.               y  = foldyinitx + cy + foldxinity;
  1089.                         }
  1090.               break;
  1091.  
  1092.             case TYPE_BARNSLEY_3:
  1093.               foldxinitx  = oldx * oldx;
  1094.               foldyinity  = oldy * oldy;
  1095.               foldxinity  = oldx * oldy;
  1096.               /* orbit calculation */
  1097.               if(oldx > 0)
  1098.             {
  1099.               xx = foldxinitx - foldyinity - 1.0;
  1100.               y  = foldxinity * 2;
  1101.             }
  1102.               else
  1103.             {
  1104.               xx = foldxinitx - foldyinity -1.0 + cx * oldx;
  1105.               y  = foldxinity * 2;
  1106.               y += cy * oldx;
  1107.             }
  1108.               break;
  1109.  
  1110.             case TYPE_SPIDER:
  1111.               /* { c=z=pixel: z=z*z+c; c=c/2+z, |z|<=4 } */
  1112.               xx = x*x - y*y + tmpx + cx;
  1113.               y = 2 * oldx * oldy + tmpy +cy;
  1114.               tmpx = tmpx/2 + xx;
  1115.               tmpy = tmpy/2 + y;
  1116.               break;
  1117.  
  1118.             case TYPE_MAN_O_WAR:
  1119.               xx = x*x - y*y + tmpx + cx;
  1120.               y = 2.0 * x * y + tmpy + cy;
  1121.               tmpx = oldx;
  1122.               tmpy = oldy;
  1123.               break;
  1124.  
  1125.             case TYPE_LAMBDA:
  1126.               tempsqrx = x * x;
  1127.               tempsqry = y * y;
  1128.               tempsqrx = oldx - tempsqrx + tempsqry;
  1129.               tempsqry = -(oldy * oldx);
  1130.               tempsqry += tempsqry + oldy;
  1131.               xx = cx * tempsqrx - cy * tempsqry;
  1132.               y = cx * tempsqry + cy * tempsqrx;
  1133.               break;
  1134.  
  1135.             case TYPE_SIERPINSKI:
  1136.               xx = oldx + oldx;
  1137.               y = oldy + oldy;
  1138.               if (oldy > .5)
  1139.             y = y - 1;
  1140.               else if (oldx > .5)
  1141.             xx = xx - 1;
  1142.               break;
  1143.  
  1144.             default:
  1145.               break;
  1146.             }
  1147.  
  1148.           x = xx;
  1149.         }
  1150.  
  1151.           if (useloglog)
  1152.         {
  1153.           adjust = log (log (x * x + y * y) / 2) / log (2);
  1154.         }
  1155.           else
  1156.         {
  1157.           adjust = 0.0;
  1158.         }
  1159.           color = (int) (((zaehler - adjust) *
  1160.                   (wvals.ncolors - 1)) / iteration);
  1161.           p_ul[0] = colormap[color][0];
  1162.           p_ul[1] = colormap[color][1];
  1163.           p_ul[2] = colormap[color][2];
  1164.           p_ul += 3;
  1165.           px += 1;
  1166.         } /* for */
  1167.       py += 1;
  1168.     } /* for */
  1169.  
  1170.       p = wint.wimage;
  1171.  
  1172.       for (y = 0; y < preview_height; y++)
  1173.     {
  1174.       gtk_preview_draw_row (GTK_PREVIEW (wint.preview), p,
  1175.                 0, y, preview_width);
  1176.       p += preview_width * 3;
  1177.     }
  1178.  
  1179.       gtk_widget_draw (wint.preview, NULL);
  1180.       gdk_flush ();
  1181.     }
  1182. }
  1183.  
  1184. /**********************************************************************
  1185.  FUNCTION: set_cmap_preview()
  1186.  *********************************************************************/
  1187.  
  1188. void
  1189. set_cmap_preview (void)
  1190. {
  1191.   gint    i;
  1192.   gint    x;
  1193.   gint    y;
  1194.   gint    j;
  1195.   guchar *b;
  1196.   guchar  c[GR_WIDTH * 3];
  1197.   gint    xsize, ysize;
  1198.  
  1199.   if (NULL == cmap_preview)
  1200.     return;
  1201.  
  1202.   make_color_map ();
  1203.  
  1204.   for (ysize = 1; ysize * ysize * ysize < wvals.ncolors; ysize++) /**/;
  1205.   xsize = wvals.ncolors / ysize;
  1206.   while (xsize * ysize < wvals.ncolors) xsize++;
  1207.   b = g_new (guchar, xsize * 3);
  1208.  
  1209.   gtk_preview_size     (GTK_PREVIEW (cmap_preview), xsize, ysize * 4);
  1210.   gtk_widget_set_usize (GTK_WIDGET (cmap_preview),  xsize, ysize * 4);
  1211.     
  1212.   for (y = 0; y < ysize*4; y += 4)
  1213.     {
  1214.       for (x = 0; x < xsize; x++)
  1215.     {
  1216.       i = x + (y / 4) * xsize;
  1217.       if (i > wvals.ncolors)
  1218.         {
  1219.           for (j = 0; j < 3; j++) 
  1220.         b[x * 3 + j] = 0;
  1221.         }
  1222.       else
  1223.         {
  1224.           for (j = 0; j < 3; j++)
  1225.         b[x * 3 + j] = colormap[i][j];
  1226.         }
  1227.     }
  1228.  
  1229.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y, xsize);
  1230.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y + 1, xsize);
  1231.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y + 2, xsize);
  1232.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y + 3, xsize);
  1233.     }
  1234.  
  1235.   for (x = 0; x < GR_WIDTH; x++)
  1236.     {
  1237.       for (j = 0; j < 3; j++)
  1238.     c[x * 3 + j] = colormap[(int)((float)x/(float)GR_WIDTH*256.0)][j];
  1239.     }
  1240.  
  1241.   gtk_widget_draw (cmap_preview, NULL);
  1242.  
  1243.   g_free (b);
  1244. }
  1245.  
  1246. /**********************************************************************
  1247.  FUNCTION: make_color_map()
  1248.  *********************************************************************/
  1249.  
  1250. void
  1251. make_color_map (void)
  1252. {
  1253.   gint     i;
  1254.   gint     j;
  1255.   gint     r;
  1256.   gint     gr;
  1257.   gint     bl;
  1258.   gdouble  redstretch;
  1259.   gdouble  greenstretch;
  1260.   gdouble  bluestretch;
  1261.   gdouble  pi = atan (1) * 4;
  1262.  
  1263.   redstretch   = wvals.redstretch * 127.5;
  1264.   greenstretch = wvals.greenstretch * 127.5;
  1265.   bluestretch  = wvals.bluestretch * 127.5;
  1266.  
  1267.   for (i = 0; i < wvals.ncolors; i++)
  1268.     if (wvals.colormode == 1)
  1269.       {
  1270.     for (j = 0; j < 3; j++)
  1271.       colormap[i][j] = (int) (gradient_samples[i * 4 + j] * 255.0);
  1272.       }
  1273.     else
  1274.       {
  1275.     double x = (i*2.0) / wvals.ncolors;
  1276.     r = gr = bl = 0;
  1277.  
  1278.     switch (wvals.redmode)
  1279.       {
  1280.       case SINUS:
  1281.         r = (int) redstretch *(1.0 + sin((x - 1) * pi));
  1282.         break;
  1283.       case COSINUS:
  1284.         r = (int) redstretch *(1.0 + cos((x - 1) * pi));
  1285.         break;
  1286.       case NONE:
  1287.         r = (int)(redstretch *(x));
  1288.         break;
  1289.       default:
  1290.         break;
  1291.       }
  1292.  
  1293.     switch (wvals.greenmode)
  1294.       {
  1295.       case SINUS:
  1296.         gr = (int) greenstretch *(1.0 + sin((x - 1) * pi));
  1297.         break;
  1298.       case COSINUS:
  1299.         gr = (int) greenstretch *(1.0 + cos((x - 1) * pi));
  1300.         break;
  1301.       case NONE:
  1302.         gr = (int)(greenstretch *(x));
  1303.         break;
  1304.       default:
  1305.         break;
  1306.       }
  1307.  
  1308.     switch (wvals.bluemode)
  1309.       {
  1310.       case SINUS:
  1311.         bl = (int) bluestretch * (1.0 + sin ((x - 1) * pi));
  1312.         break;
  1313.       case COSINUS:
  1314.         bl = (int) bluestretch * (1.0 + cos ((x - 1) * pi));
  1315.         break;
  1316.       case NONE:
  1317.         bl = (int) (bluestretch * x);
  1318.         break;
  1319.       default:
  1320.         break;
  1321.       }
  1322.  
  1323.     r  = MIN (r,  255);
  1324.     gr = MIN (gr, 255);
  1325.     bl = MIN (bl, 255);
  1326.  
  1327.     if (wvals.redinvert)
  1328.       r = 255 - r;
  1329.  
  1330.     if (wvals.greeninvert)
  1331.       gr = 255 - gr;
  1332.  
  1333.     if (wvals.blueinvert)
  1334.       bl = 255 - bl;
  1335.  
  1336.     colormap[i][0] = r;
  1337.     colormap[i][1] = gr;
  1338.     colormap[i][2] = bl;
  1339.       }
  1340. }
  1341.  
  1342. /**********************************************************************
  1343.  FUNCTION: explorer_logo_dialog
  1344.  *********************************************************************/
  1345.  
  1346. static void
  1347. explorer_logo_dialog (void)
  1348. {
  1349.   GtkWidget *xdlg;
  1350.   GtkWidget *xlabel = NULL;
  1351.   GtkWidget *xlogo_box;
  1352.   GtkWidget *xpreview;
  1353.   GtkWidget *xframe;
  1354.   GtkWidget *xframe2;
  1355.   GtkWidget *xframe3;
  1356.   GtkWidget *xvbox;
  1357.   GtkWidget *xhbox;
  1358.   GtkWidget *vpaned;
  1359.   guchar *temp;
  1360.   guchar *temp2;
  1361.   guchar *datapointer;
  1362.   gint    y;
  1363.   gint    x;
  1364.  
  1365.   if (logodlg)
  1366.     {
  1367.       gdk_window_raise (logodlg->window);
  1368.       return;
  1369.     }
  1370.  
  1371.   xdlg = logodlg =
  1372.     gimp_dialog_new (_("About"), "fractalexplorer",
  1373.              gimp_standard_help_func, "filters/fractalexplorer.html",
  1374.              GTK_WIN_POS_MOUSE,
  1375.              FALSE, TRUE, FALSE,
  1376.  
  1377.              _("OK"), gtk_widget_destroy,
  1378.              NULL, 1, NULL, TRUE, TRUE,
  1379.  
  1380.              NULL);
  1381.  
  1382.   gtk_signal_connect (GTK_OBJECT (xdlg), "destroy",
  1383.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1384.               &logodlg);
  1385.  
  1386.   xframe = gtk_frame_new (NULL);
  1387.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_ETCHED_IN);
  1388.   gtk_container_set_border_width (GTK_CONTAINER (xframe), 6);
  1389.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (xdlg)->vbox), xframe, TRUE, TRUE, 0);
  1390.  
  1391.   xvbox = gtk_vbox_new (FALSE, 4);
  1392.   gtk_container_set_border_width (GTK_CONTAINER (xvbox), 4);
  1393.   gtk_container_add (GTK_CONTAINER (xframe), xvbox);
  1394.  
  1395.   /*  The logo frame & drawing area  */
  1396.   xhbox = gtk_hbox_new (FALSE, 5);
  1397.   gtk_box_pack_start (GTK_BOX (xvbox), xhbox, FALSE, TRUE, 0);
  1398.  
  1399.   xlogo_box = gtk_vbox_new (FALSE, 0);
  1400.   gtk_box_pack_start (GTK_BOX (xhbox), xlogo_box, FALSE, FALSE, 0);
  1401.  
  1402.   xframe2 = gtk_frame_new (NULL);
  1403.   gtk_frame_set_shadow_type(GTK_FRAME(xframe2), GTK_SHADOW_IN);
  1404.   gtk_box_pack_start(GTK_BOX(xlogo_box), xframe2, FALSE, FALSE, 0);
  1405.  
  1406.   xpreview = gtk_preview_new (GTK_PREVIEW_COLOR);
  1407.   gtk_preview_size (GTK_PREVIEW (xpreview), logo_width, logo_height);
  1408.   temp = g_malloc ((logo_width + 10) * 3);
  1409.   datapointer = header_data + logo_width * logo_height - 1;
  1410.  
  1411.   for (y = 0; y < logo_height; y++)
  1412.     {
  1413.       temp2 = temp;
  1414.       for (x = 0; x < logo_width; x++)
  1415.     {
  1416.       HEADER_PIXEL(datapointer, temp2);
  1417.       temp2 += 3;
  1418.     }
  1419.       gtk_preview_draw_row(GTK_PREVIEW(xpreview),
  1420.                temp,
  1421.                0, y, logo_width);
  1422.     }
  1423.  
  1424.   g_free (temp);
  1425.   gtk_container_add (GTK_CONTAINER (xframe2), xpreview);
  1426.   gtk_widget_show (xpreview);
  1427.   gtk_widget_show (xframe2);
  1428.   gtk_widget_show (xlogo_box);
  1429.   gtk_widget_show (xhbox);
  1430.  
  1431.   xhbox = gtk_hbox_new (FALSE, 5);
  1432.   gtk_box_pack_start (GTK_BOX (xvbox), xhbox, TRUE, TRUE, 0);
  1433.  
  1434.   vpaned = gtk_vpaned_new ();
  1435.   gtk_box_pack_start (GTK_BOX (xhbox), vpaned, TRUE, TRUE, 0);
  1436.   gtk_widget_show (vpaned);
  1437.     
  1438.   xframe3 = gtk_frame_new (NULL);
  1439.   gtk_paned_add1 (GTK_PANED (vpaned), xframe3);
  1440.   gtk_widget_show (xframe3);
  1441.  
  1442.   xlabel = gtk_label_new ("\nCotting Software Productions\n"
  1443.               "Quellenstrasse 10\n"
  1444.               "CH-8005 Zuerich (Switzerland)\n\n"
  1445.               "cotting@multimania.com\n"
  1446.               "http://www.multimania.com/cotting\n\n"
  1447.               "Fractal Chaos Explorer\nPlug-In for the GIMP\n"
  1448.               "Version 2.00 Beta 2 (Multilingual)\n");
  1449.   gtk_container_add (GTK_CONTAINER (xframe3),  xlabel);
  1450.   gtk_widget_show (xlabel);
  1451.  
  1452.   xframe3 = gtk_frame_new (NULL);
  1453.   gtk_paned_add2 (GTK_PANED (vpaned), xframe3);
  1454.   gtk_widget_show (xframe3);
  1455.  
  1456.   xlabel = gtk_label_new ("\nContains code from:\n\n"
  1457.               "Daniel Cotting\n<cotting@mygale.org>\n"
  1458.               "Peter Kirchgessner\n<Pkirchg@aol.com>\n"
  1459.               "Scott Draves\n<spot@cs.cmu.edu>\n"
  1460.               "Andy Thomas\n<alt@picnic.demon.co.uk>\n"
  1461.               "and the GIMP distribution.\n");
  1462.   gtk_container_add (GTK_CONTAINER (xframe3),  xlabel);
  1463.   gtk_widget_show (xlabel);
  1464.  
  1465.   gtk_widget_show (xhbox);
  1466.  
  1467.   gtk_widget_show (xvbox);
  1468.   gtk_widget_show (xframe);
  1469.   gtk_widget_show (xdlg);
  1470. }
  1471.  
  1472. /**********************************************************************
  1473.  FUNCTION: dialog_change_scale
  1474.  *********************************************************************/
  1475.  
  1476. void
  1477. dialog_change_scale (void)
  1478. {
  1479.   ready_now = FALSE;
  1480.  
  1481.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->xmin), wvals.xmin);
  1482.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->xmax), wvals.xmax);
  1483.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->ymin), wvals.ymin);
  1484.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->ymax), wvals.ymax);
  1485.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->iter), wvals.iter);
  1486.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->cx),   wvals.cx);
  1487.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->cy),   wvals.cy);
  1488.  
  1489.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->red),  wvals.redstretch);
  1490.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->green),wvals.greenstretch);
  1491.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->blue), wvals.bluestretch);
  1492.  
  1493.   gtk_toggle_button_set_active
  1494.     (GTK_TOGGLE_BUTTON (elements->type[wvals.fractaltype]), TRUE);
  1495.  
  1496.   gtk_toggle_button_set_active
  1497.     (GTK_TOGGLE_BUTTON (elements->redmode[wvals.redmode]), TRUE);
  1498.   gtk_toggle_button_set_active
  1499.     (GTK_TOGGLE_BUTTON (elements->greenmode[wvals.greenmode]), TRUE);
  1500.   gtk_toggle_button_set_active
  1501.     (GTK_TOGGLE_BUTTON (elements->bluemode[wvals.bluemode]), TRUE);
  1502.  
  1503.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (elements->redinvert),
  1504.                 wvals.redinvert);
  1505.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (elements->greeninvert),
  1506.                 wvals.greeninvert);
  1507.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (elements->blueinvert),
  1508.                 wvals.blueinvert);
  1509.  
  1510.   gtk_toggle_button_set_active
  1511.     (GTK_TOGGLE_BUTTON (elements->colormode[wvals.colormode]), TRUE);
  1512.  
  1513.   ready_now = TRUE;
  1514. }
  1515.  
  1516.  
  1517. /**********************************************************************
  1518.  FUNCTION: save_options
  1519.  *********************************************************************/
  1520.  
  1521. void
  1522. save_options (FILE * fp)
  1523. {
  1524.   /* Save options */
  1525.   
  1526.   fprintf (fp, "fractaltype: %i\n", wvals.fractaltype);
  1527.   fprintf (fp, "xmin: %0.15f\n", wvals.xmin);
  1528.   fprintf (fp, "xmax: %0.15f\n", wvals.xmax);
  1529.   fprintf (fp, "ymin: %0.15f\n", wvals.ymin);
  1530.   fprintf (fp, "ymax: %0.15f\n", wvals.ymax);
  1531.   fprintf (fp, "iter: %0.15f\n", wvals.iter);
  1532.   fprintf (fp, "cx: %0.15f\n", wvals.cx);
  1533.   fprintf (fp, "cy: %0.15f\n", wvals.cy);
  1534.   fprintf (fp, "redstretch: %0.15f\n", wvals.redstretch * 128.0);
  1535.   fprintf (fp, "greenstretch: %0.15f\n", wvals.greenstretch * 128.0);
  1536.   fprintf (fp, "bluestretch: %0.15f\n", wvals.bluestretch * 128.0);
  1537.   fprintf (fp, "redmode: %i\n", wvals.redmode);
  1538.   fprintf (fp, "greenmode: %i\n", wvals.greenmode);
  1539.   fprintf (fp, "bluemode: %i\n", wvals.bluemode);
  1540.   fprintf (fp, "redinvert: %i\n", wvals.redinvert);
  1541.   fprintf (fp, "greeninvert: %i\n", wvals.greeninvert);
  1542.   fprintf (fp, "blueinvert: %i\n", wvals.blueinvert);
  1543.   fprintf (fp, "colormode: %i\n", wvals.colormode);
  1544.   fputs ("#**********************************************************************\n", fp);
  1545.   fprintf(fp, "<EOF>\n");
  1546.   fputs ("#**********************************************************************\n", fp);
  1547. }
  1548.  
  1549. /**********************************************************************
  1550.  FUNCTION: save_callback
  1551.  *********************************************************************/
  1552.  
  1553. void
  1554. save_callback (void)
  1555. {
  1556.   FILE  *fp;
  1557.   gchar *savename;
  1558.   gchar *message;
  1559.  
  1560.   savename = filename;
  1561.  
  1562.   fp = fopen (savename, "wt+");
  1563.  
  1564.   if (!fp) 
  1565.     {
  1566.       message = g_strconcat (_("Error opening: %s"), 
  1567.                  "\n",
  1568.                  _("Could not save."), 
  1569.                  savename);
  1570.       g_message (message);
  1571.       g_free (message);
  1572.       return;
  1573.     }
  1574.   /* Write header out */
  1575.   fputs (FRACTAL_HEADER, fp);
  1576.   fputs ("#**********************************************************************\n", fp);
  1577.   fputs ("# This is a data file for the Fractal Explorer plug-in for the GIMP   *\n", fp);
  1578.   fputs ("# Get the plug-in at              http://www.multimania.com/cotting   *\n", fp);
  1579.   fputs ("#**********************************************************************\n", fp);
  1580.  
  1581.   save_options (fp);
  1582.  
  1583.   if (ferror (fp))
  1584.     g_message (_("Failed to write file\n"));
  1585.   fclose (fp);
  1586. }
  1587.  
  1588. /**********************************************************************
  1589.  FUNCTION: file_selection_ok
  1590.  *********************************************************************/
  1591.  
  1592. void
  1593. file_selection_ok (GtkWidget        *w,
  1594.            GtkFileSelection *fs,
  1595.            gpointer          data)
  1596. {
  1597.   gchar       *filenamebuf;
  1598.   struct stat  filestat;
  1599.   gint         err;
  1600.  
  1601.   filenamebuf = gtk_file_selection_get_filename (GTK_FILE_SELECTION(fs));
  1602.  
  1603.   /* Get the name */
  1604.   if (strlen (filenamebuf) == 0)
  1605.     {
  1606.       g_message (_("Save: No filename given"));
  1607.       return;
  1608.     }
  1609.  
  1610.   /* Check if directory exists */
  1611.   err = stat (filenamebuf, &filestat);
  1612.  
  1613.   if (!err && S_ISDIR (filestat.st_mode))
  1614.     {
  1615.       /* Can't save to directory */
  1616.       g_message (_("Save: Can't save to a directory"));
  1617.       return;
  1618.     }
  1619.  
  1620.   filename = g_strdup (filenamebuf);
  1621.   save_callback ();
  1622.   gtk_widget_destroy (GTK_WIDGET (fs));
  1623. }
  1624.  
  1625. /**********************************************************************
  1626.  FUNCTION: load_file_selection_ok
  1627. **********************************************************************/
  1628.  
  1629. void
  1630. load_file_selection_ok (GtkWidget        *w,
  1631.             GtkFileSelection *fs,
  1632.             gpointer          data)
  1633. {
  1634.   struct stat filestat;
  1635.   gint        err;
  1636.  
  1637.   filename = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
  1638.  
  1639.   err = stat (filename, &filestat);
  1640.  
  1641.   if (!err && S_ISREG (filestat.st_mode))
  1642.     {
  1643.       explorer_load ();
  1644.     }
  1645.  
  1646.   gtk_widget_destroy (GTK_WIDGET (fs));
  1647.   gtk_widget_show (maindlg);
  1648.   dialog_change_scale ();
  1649.   set_cmap_preview ();
  1650.   dialog_update_preview ();
  1651. }
  1652.  
  1653. /**********************************************************************
  1654.  FUNCTION: create_load_file_selection
  1655.  *********************************************************************/
  1656.  
  1657. void
  1658. create_load_file_selection (void)
  1659. {
  1660.   static GtkWidget *window = NULL;
  1661.  
  1662.   /* Load a single object */
  1663.   if (!window)
  1664.     {
  1665.       window = gtk_file_selection_new (_("Load Fractal Parameters"));
  1666.       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_NONE);
  1667.  
  1668.       gtk_signal_connect (GTK_OBJECT (window), "destroy",
  1669.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1670.               &window);
  1671.  
  1672.       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
  1673.               "clicked",
  1674.               GTK_SIGNAL_FUNC (load_file_selection_ok),
  1675.               (gpointer) window);
  1676.       gimp_help_set_help_data (GTK_FILE_SELECTION(window)->ok_button, _("Click here to load your file"), NULL);
  1677.  
  1678.       gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (window)->cancel_button),
  1679.                  "clicked",
  1680.                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1681.                  GTK_OBJECT (window));
  1682.       gimp_help_set_help_data (GTK_FILE_SELECTION(window)->cancel_button, _("Click here to cancel load procedure"), NULL);
  1683.     }
  1684.  
  1685.   if (!GTK_WIDGET_VISIBLE (window))
  1686.     gtk_widget_show (window);
  1687. }
  1688.  
  1689. /**********************************************************************
  1690.  FUNCTION: create_file_selection
  1691.  *********************************************************************/
  1692.  
  1693. void
  1694. create_file_selection (void)
  1695. {
  1696.   static GtkWidget *window = NULL;
  1697.  
  1698.   if (!window)
  1699.     {
  1700.       window = gtk_file_selection_new (_("Save Fractal Parameters"));
  1701.       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_NONE);
  1702.  
  1703.       gtk_signal_connect (GTK_OBJECT (window), "destroy",
  1704.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1705.               &window);
  1706.  
  1707.       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
  1708.               "clicked",
  1709.               GTK_SIGNAL_FUNC (file_selection_ok),
  1710.               (gpointer) window);
  1711.       gimp_help_set_help_data (GTK_FILE_SELECTION(window)->ok_button,
  1712.                    _("Click here to save your file"), NULL);
  1713.  
  1714.       gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(window)->cancel_button),
  1715.                  "clicked",
  1716.                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1717.                  GTK_OBJECT (window));
  1718.       gimp_help_set_help_data (GTK_FILE_SELECTION (window)->cancel_button,
  1719.                    _("Click here to cancel save procedure"), NULL);
  1720.     }
  1721.   if (tpath)
  1722.     {
  1723.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), tpath);
  1724.     }
  1725.   else if (fractalexplorer_path_list)
  1726.     {
  1727.       gchar *dir;
  1728.  
  1729.       dir = gimp_path_get_user_writable_dir (fractalexplorer_path_list);
  1730.  
  1731.       if (!dir)
  1732.     dir = g_strdup (gimp_directory ());
  1733.  
  1734.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), dir);
  1735.  
  1736.       g_free (dir);
  1737.     }
  1738.   else
  1739.     gtk_file_selection_set_filename (GTK_FILE_SELECTION (window),"/tmp");
  1740.  
  1741.   if (!GTK_WIDGET_VISIBLE (window))
  1742.     gtk_widget_show (window);
  1743. }
  1744.  
  1745. /**********************************************************************
  1746.  FUNCTION: get_line
  1747.  *********************************************************************/
  1748.  
  1749. gchar *
  1750. get_line (gchar *buf,
  1751.       gint   s,
  1752.       FILE  *from,
  1753.       gint   init)
  1754. {
  1755.   gint   slen;
  1756.   gchar *ret;
  1757.  
  1758.   if (init)
  1759.     line_no = 1;
  1760.   else
  1761.     line_no++;
  1762.  
  1763.   do
  1764.     {
  1765.       ret = fgets (buf, s, from);
  1766.     }
  1767.   while (!ferror (from) && buf[0] == '#');
  1768.  
  1769.   slen = strlen (buf);
  1770.  
  1771.   /* The last newline is a pain */
  1772.   if (slen > 0)
  1773.     buf[slen - 1] = '\0';
  1774.  
  1775.   if (ferror (from))
  1776.     {
  1777.       g_warning ("Error reading file");
  1778.       return NULL;
  1779.     }
  1780.  
  1781.   return ret;
  1782. }
  1783.  
  1784. /**********************************************************************
  1785.  FUNCTION: load_options
  1786.  *********************************************************************/
  1787.  
  1788. gint
  1789. load_options (fractalexplorerOBJ *xxx,
  1790.           FILE               *fp)
  1791. {
  1792.   gchar load_buf[MAX_LOAD_LINE];
  1793.   gchar str_buf[MAX_LOAD_LINE];
  1794.   gchar opt_buf[MAX_LOAD_LINE];
  1795.  
  1796.   /*  default values  */
  1797.   xxx->opts.fractaltype   =   0;
  1798.   xxx->opts.xmin          =  -2.0;
  1799.   xxx->opts.xmax          =   2.0;
  1800.   xxx->opts.ymin          =  -1.5;
  1801.   xxx->opts.ymax          =   1.5;
  1802.   xxx->opts.iter          =  50.0;
  1803.   xxx->opts.cx            =  -0.75;
  1804.   xxx->opts.cy            =  -0.2;
  1805.   xxx->opts.colormode     =   0;
  1806.   xxx->opts.redstretch    =   1.0;
  1807.   xxx->opts.greenstretch  =   1.0;
  1808.   xxx->opts.bluestretch   =   1.0;
  1809.   xxx->opts.redmode       =   1;
  1810.   xxx->opts.greenmode     =   1;
  1811.   xxx->opts.bluemode      =   1;
  1812.   xxx->opts.redinvert     =   0;
  1813.   xxx->opts.greeninvert   =   0;
  1814.   xxx->opts.blueinvert    =   0;
  1815.   xxx->opts.alwayspreview =   1;
  1816.   xxx->opts.ncolors       = 256;  /*  not saved  */
  1817.  
  1818.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1819.  
  1820.   while (!feof (fp) && strcmp (load_buf, "<EOF>"))
  1821.     {
  1822.       /* Get option name */
  1823.       sscanf (load_buf, "%s %s", str_buf, opt_buf);
  1824.  
  1825.       if (!strcmp (str_buf, "fractaltype:"))
  1826.     {
  1827.       gint sp = 0;
  1828.  
  1829.       sp = atoi (opt_buf);
  1830.       if (sp < 0)
  1831.         return -1;
  1832.       xxx->opts.fractaltype = sp;
  1833.     }
  1834.       else if (!strcmp (str_buf, "xmin:"))
  1835.     {
  1836.       gdouble sp = 0;
  1837.  
  1838.       sp = atof (opt_buf);
  1839.       xxx->opts.xmin = sp;
  1840.     }
  1841.       else if (!strcmp (str_buf, "xmax:"))
  1842.     {
  1843.       gdouble sp = 0;
  1844.  
  1845.       sp = atof (opt_buf);
  1846.       xxx->opts.xmax = sp;
  1847.     }
  1848.       else if (!strcmp(str_buf, "ymin:"))
  1849.     {
  1850.       gdouble sp = 0;
  1851.  
  1852.       sp = atof (opt_buf);
  1853.       xxx->opts.ymin = sp;
  1854.     }
  1855.       else if (!strcmp (str_buf, "ymax:"))
  1856.     {
  1857.       gdouble sp = 0;
  1858.  
  1859.       sp = atof (opt_buf);
  1860.       xxx->opts.ymax = sp;
  1861.     }
  1862.       else if (!strcmp(str_buf, "redstretch:"))
  1863.     {
  1864.       gdouble sp = 0;
  1865.  
  1866.       sp = atof (opt_buf);
  1867.       xxx->opts.redstretch = sp / 128.0;
  1868.     }
  1869.       else if (!strcmp(str_buf, "greenstretch:"))
  1870.     {
  1871.       gdouble sp = 0;
  1872.  
  1873.       sp = atof (opt_buf);
  1874.       xxx->opts.greenstretch = sp / 128.0;
  1875.     }
  1876.       else if (!strcmp (str_buf, "bluestretch:"))
  1877.     {
  1878.       gdouble sp = 0;
  1879.  
  1880.       sp = atof (opt_buf);
  1881.       xxx->opts.bluestretch = sp / 128.0;
  1882.     }
  1883.       else if (!strcmp (str_buf, "iter:"))
  1884.     {
  1885.       gdouble sp = 0;
  1886.  
  1887.       sp = atof (opt_buf);
  1888.       xxx->opts.iter = sp;
  1889.     }
  1890.       else if (!strcmp(str_buf, "cx:"))
  1891.     {
  1892.       gdouble sp = 0;
  1893.  
  1894.       sp = atof (opt_buf);
  1895.       xxx->opts.cx = sp;
  1896.     }
  1897.       else if (!strcmp (str_buf, "cy:"))
  1898.     {
  1899.       gdouble sp = 0;
  1900.  
  1901.       sp = atof (opt_buf);
  1902.       xxx->opts.cy = sp;
  1903.     }
  1904.       else if (!strcmp(str_buf, "redmode:"))
  1905.     {
  1906.       gint sp = 0;
  1907.  
  1908.       sp = atoi (opt_buf);
  1909.       xxx->opts.redmode = sp;
  1910.     }
  1911.       else if (!strcmp(str_buf, "greenmode:"))
  1912.     {
  1913.       gint sp = 0;
  1914.  
  1915.       sp = atoi (opt_buf);
  1916.       xxx->opts.greenmode = sp;
  1917.     }
  1918.       else if (!strcmp(str_buf, "bluemode:"))
  1919.     {
  1920.       gint sp = 0;
  1921.  
  1922.       sp = atoi (opt_buf);
  1923.       xxx->opts.bluemode = sp;
  1924.     }
  1925.       else if (!strcmp (str_buf, "redinvert:"))
  1926.     {
  1927.       gint sp = 0;
  1928.  
  1929.       sp = atoi (opt_buf);
  1930.       xxx->opts.redinvert = sp;
  1931.     }
  1932.       else if (!strcmp (str_buf, "greeninvert:"))
  1933.     {
  1934.       gint sp = 0;
  1935.  
  1936.       sp = atoi (opt_buf);
  1937.       xxx->opts.greeninvert = sp;
  1938.     }
  1939.       else if (!strcmp(str_buf, "blueinvert:"))
  1940.     {
  1941.       gint sp = 0;
  1942.  
  1943.       sp = atoi (opt_buf);
  1944.       xxx->opts.blueinvert = sp;
  1945.     }
  1946.       else if (!strcmp (str_buf, "colormode:"))
  1947.     {
  1948.       gint sp = 0;
  1949.  
  1950.       sp = atoi (opt_buf);
  1951.       xxx->opts.colormode = sp;
  1952.     }
  1953.  
  1954.       get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1955.     }
  1956.  
  1957.   return 0;
  1958. }
  1959.  
  1960. /**********************************************************************
  1961.  FUNCTION: explorer_load
  1962.  *********************************************************************/
  1963.  
  1964. void
  1965. explorer_load (void)
  1966. {
  1967.   FILE  *fp;
  1968.   gchar  load_buf[MAX_LOAD_LINE];
  1969.  
  1970.   g_assert (filename != NULL); 
  1971.   fp = fopen (filename, "rt");
  1972.  
  1973.   if (!fp)
  1974.     {
  1975.       g_warning ("Error opening: %s", filename);
  1976.       return;
  1977.     }
  1978.   get_line (load_buf, MAX_LOAD_LINE, fp, 1);
  1979.  
  1980.   if (strncmp (FRACTAL_HEADER, load_buf, strlen (load_buf)))
  1981.     {
  1982.       g_message (_("File '%s' is not a FractalExplorer file"), filename);
  1983.       return;
  1984.     }
  1985.   if (load_options (current_obj,fp))
  1986.     {
  1987.       g_message (_("File '%s' is corrupt.\nLine %d Option section incorrect"), 
  1988.          filename, line_no);
  1989.       return;
  1990.     }
  1991.  
  1992.   wvals = current_obj->opts;
  1993.   fclose (fp);
  1994. }
  1995.