home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / script-fu / script-fu-console.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  18.4 KB  |  641 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <sys/types.h>
  25. #if HAVE_DIRENT_H
  26. #include <dirent.h>
  27. #endif
  28. #if HAVE_UNISTD_H
  29. #include <unistd.h>
  30. #endif
  31. #include <sys/stat.h>
  32.  
  33. #include "gdk/gdkkeysyms.h"
  34. #include "gtk/gtk.h"
  35.  
  36. #include "libgimp/gimp.h"
  37. #include "libgimp/gimpui.h"
  38.  
  39. #include "script-fu-intl.h"
  40.  
  41. #include "siod.h"
  42. #include "script-fu-console.h"
  43.  
  44. #include <plug-ins/dbbrowser/dbbrowser_utils.h>
  45.  
  46. #ifdef G_OS_WIN32
  47. #include <fcntl.h>
  48. #include <io.h>
  49. #endif
  50.  
  51. #define TEXT_WIDTH  400
  52. #define TEXT_HEIGHT 400
  53. #define ENTRY_WIDTH 400
  54.  
  55. #define BUFSIZE 256
  56.  
  57. typedef struct
  58. {
  59.   GtkWidget *console;
  60.   GtkWidget *cc;
  61.   GtkAdjustment *vadj;
  62.  
  63.   GdkFont   *font_strong;
  64.   GdkFont   *font_emphasis;
  65.   GdkFont   *font_weak;
  66.   GdkFont   *font;
  67.  
  68.   gint32     input_id;
  69. } ConsoleInterface;
  70.  
  71. /*
  72.  *  Local Functions
  73.  */
  74.  
  75. static void  script_fu_console_interface (void);
  76. static void  script_fu_close_callback    (GtkWidget        *widget,
  77.                       gpointer          data);
  78. static void  script_fu_browse_callback    (GtkWidget        *widget,
  79.                       gpointer          data);
  80. static gboolean script_fu_siod_read      (GIOChannel  *channel,
  81.                       GIOCondition cond,
  82.                       gpointer     data);
  83. static gint  script_fu_cc_is_empty       (void);
  84. static gint  script_fu_cc_key_function   (GtkWidget         *widget,
  85.                       GdkEventKey       *event,
  86.                       gpointer           data);
  87.  
  88. static FILE *script_fu_open_siod_console (void);
  89. static void  script_fu_close_siod_console(void);
  90.  
  91. /*
  92.  *  Local variables
  93.  */
  94.  
  95. static ConsoleInterface cint =
  96. {
  97.   NULL,  /*  console  */
  98.   NULL,  /*  current command  */
  99.   NULL,  /*  vertical adjustment  */
  100.  
  101.   NULL,  /*  strong font  */
  102.   NULL,  /*  emphasis font  */
  103.   NULL,  /*  weak font  */
  104.   NULL,  /*  normal font  */
  105.  
  106.   -1     /*  input id  */
  107. };
  108.  
  109. static char   read_buffer[BUFSIZE];
  110. static GList *history = NULL;
  111. static int    history_len = 0;
  112. static int    history_cur = 0;
  113. static int    history_max = 50;
  114.  
  115. static int   siod_output_pipe[2];
  116. extern int   siod_verbose_level;
  117. extern char  siod_err_msg[];
  118. extern FILE *siod_output;
  119.  
  120.  
  121. #define message(string) printf("(%s): %d ::: %s\n", __PRETTY_FUNCTION__, __LINE__, string)
  122.  
  123. /*
  124.  *  Function definitions
  125.  */
  126.  
  127. void
  128. script_fu_console_run (char     *name,
  129.                int       nparams,
  130.                GimpParam   *params,
  131.                int      *nreturn_vals,
  132.                GimpParam  **return_vals)
  133. {
  134.   static GimpParam values[1];
  135.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  136.   GimpRunModeType run_mode;
  137.  
  138.   run_mode = params[0].data.d_int32;
  139.  
  140.   switch (run_mode)
  141.     {
  142.     case GIMP_RUN_INTERACTIVE:
  143.       /*  Enable SIOD output  */
  144.       script_fu_open_siod_console ();
  145.  
  146.       /*  Run the interface  */
  147.       script_fu_console_interface ();
  148.  
  149.       /*  Clean up  */
  150.       script_fu_close_siod_console ();
  151.       break;
  152.  
  153.     case GIMP_RUN_WITH_LAST_VALS:
  154.     case GIMP_RUN_NONINTERACTIVE:
  155.       status = GIMP_PDB_CALLING_ERROR;
  156.       gimp_message (_("Script-Fu console mode allows only interactive invocation"));
  157.       break;
  158.  
  159.     default:
  160.       break;
  161.     }
  162.  
  163.   *nreturn_vals = 1;
  164.   *return_vals = values;
  165.  
  166.   values[0].type = GIMP_PDB_STATUS;
  167.   values[0].data.d_status = status;
  168. }
  169.  
  170. static void
  171. script_fu_console_interface (void)
  172. {
  173.   GtkWidget *dlg;
  174.   GtkWidget *button;
  175.   GtkWidget *label;
  176.   GtkWidget *vsb;
  177.   GtkWidget *table;
  178.   GtkWidget *hbox;
  179.   GIOChannel *input_channel;
  180.  
  181.   INIT_I18N_UI();
  182.  
  183.   gimp_ui_init ("script-fu", FALSE);
  184.  
  185.   dlg = gtk_dialog_new ();
  186.   gtk_window_set_title (GTK_WINDOW (dlg), _("Script-Fu Console"));
  187.   gimp_help_connect_help_accel (dlg, gimp_standard_help_func, 
  188.                 "filters/script-fu.html");
  189.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  190.               (GtkSignalFunc) script_fu_close_callback,
  191.               NULL);
  192.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  193.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  194.               &dlg);
  195.   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dlg)->vbox), 2);
  196.   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dlg)->action_area), 0);
  197.  
  198.   /*  Action area  */
  199.   button = gtk_button_new_with_label (_("Close"));
  200.   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
  201.                  (GtkSignalFunc) gtk_widget_destroy,
  202.                  (gpointer)dlg);
  203.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
  204.   gtk_widget_show (button);
  205.  
  206.   /*  The info vbox  */
  207.   label = gtk_label_new (_("SIOD Output"));
  208.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  209.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), label, FALSE, TRUE, 0);
  210.   gtk_widget_show (label);
  211.  
  212.   /*  The output text widget  */
  213.   cint.vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
  214.   vsb = gtk_vscrollbar_new (cint.vadj);
  215.   cint.console = gtk_text_new (NULL, cint.vadj);
  216.   gtk_text_set_editable (GTK_TEXT (cint.console), FALSE);
  217.   gtk_widget_set_usize (cint.console, TEXT_WIDTH, TEXT_HEIGHT);
  218.  
  219.   table  = gtk_table_new (1, 2, FALSE);
  220.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
  221.  
  222.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), table, TRUE, TRUE, 0);
  223.  
  224.   gtk_table_attach (GTK_TABLE (table), vsb, 1, 2, 0, 1,
  225.             0, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  226.   gtk_table_attach (GTK_TABLE (table), cint.console, 0, 1, 0, 1,
  227.             GTK_EXPAND | GTK_SHRINK | GTK_FILL,
  228.             GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  229.  
  230.   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  231.  
  232.   cint.font_strong = gdk_font_load ("-*-helvetica-bold-r-normal-*-*-120-*-*-*-*-*-*");
  233.   cint.font_emphasis = gdk_font_load ("-*-helvetica-medium-o-normal-*-*-100-*-*-*-*-*-*");
  234.   cint.font_weak = gdk_font_load ("-*-helvetica-medium-r-normal-*-*-100-*-*-*-*-*-*");
  235.   cint.font = gdk_font_load ("-*-*-medium-r-normal-*-*-100-*-*-c-*-*-*");
  236.  
  237.   /*  Realize the widget before allowing new text to be inserted  */
  238.   gtk_widget_realize (cint.console);
  239.  
  240.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_strong, NULL, NULL,
  241.            "The GIMP - GNU Image Manipulation Program\n\n", -1);
  242.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_emphasis, NULL, NULL,
  243.            "Copyright (C) 1995-2000\n", -1);
  244.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_emphasis, NULL, NULL,
  245.            "Spencer Kimball, Peter Mattis and the GIMP Development Team\n", -1);
  246.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  247.            "\n", -1);
  248.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  249.            "This program is free software; you can redistribute it and/or modify\n", -1);
  250.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  251.            "it under the terms of the GNU General Public License as published by\n", -1);
  252.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  253.            "the Free Software Foundation; either version 2 of the License, or\n", -1);
  254.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  255.            "(at your option) any later version.\n", -1);
  256.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  257.            "\n", -1);
  258.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  259.            "This program is distributed in the hope that it will be useful,\n", -1);
  260.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  261.            "but WITHOUT ANY WARRANTY; without even the implied warranty of\n", -1);
  262.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  263.            "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", -1);
  264.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  265.            "See the GNU General Public License for more details.\n", -1);
  266.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  267.            "\n", -1);
  268.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  269.            "You should have received a copy of the GNU General Public License\n", -1);
  270.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  271.            "along with this program; if not, write to the Free Software\n", -1);
  272.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  273.            "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n", -1);
  274.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  275.            "\n\n", -1);
  276.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_strong, NULL, NULL,
  277.            "Script-Fu Console - ", -1);
  278.   gtk_text_insert (GTK_TEXT (cint.console), cint.font_emphasis, NULL, NULL,
  279.            "Interactive Scheme Development\n\n", -1);
  280.  
  281.   gtk_widget_show (vsb);
  282.   gtk_widget_show (cint.console);
  283.   gtk_widget_show (table);
  284.  
  285.   /*  The current command  */
  286.   label = gtk_label_new (_("Current Command"));
  287.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  288.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), label, FALSE, TRUE, 0);
  289.   gtk_widget_show (label);
  290.  
  291.   hbox = gtk_hbox_new ( FALSE, 0 );
  292.   gtk_widget_set_usize (hbox, ENTRY_WIDTH, 0);
  293.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), hbox, FALSE, TRUE, 0);
  294.   gtk_widget_show (hbox);
  295.     
  296.   cint.cc = gtk_entry_new ();
  297.   
  298.   gtk_box_pack_start (GTK_BOX (hbox), cint.cc, 
  299.               TRUE, TRUE, 0);
  300. /*    gtk_widget_set_usize (cint.cc, (ENTRY_WIDTH*5)/6, 0);  */
  301.   GTK_WIDGET_SET_FLAGS (cint.cc, GTK_CAN_DEFAULT);
  302.   gtk_widget_grab_default (cint.cc);
  303.   gtk_signal_connect (GTK_OBJECT (cint.cc), "key_press_event",
  304.               (GtkSignalFunc) script_fu_cc_key_function,
  305.               NULL);
  306.  
  307.   button = gtk_button_new_with_label (_("Browse..."));
  308. /*    gtk_widget_set_usize (button, (ENTRY_WIDTH)/6, 0); */
  309.   gtk_box_pack_start (GTK_BOX (hbox), button, 
  310.               FALSE, TRUE, 0);
  311.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  312.               (GtkSignalFunc) script_fu_browse_callback,
  313.               NULL);
  314.   gtk_widget_show (button);
  315.   gtk_widget_show (cint.cc);
  316.  
  317.   input_channel = g_io_channel_unix_new (siod_output_pipe[0]);
  318.   cint.input_id = g_io_add_watch (input_channel,
  319.                   G_IO_IN,
  320.                   script_fu_siod_read,
  321.                   NULL);
  322.  
  323.   /*  Initialize the history  */
  324.   history = g_list_append (history, NULL);
  325.   history_len = 1;
  326.  
  327.   gtk_widget_show (dlg);
  328.  
  329.   gtk_main ();
  330.  
  331.   g_source_remove (cint.input_id);
  332.   if (dlg)
  333.     gtk_widget_destroy (dlg);
  334.   gdk_flush ();
  335. }
  336.  
  337. static void
  338. script_fu_close_callback (GtkWidget *widget,
  339.               gpointer   data)
  340. {
  341.   gtk_main_quit ();
  342. }
  343.  
  344. void 
  345. apply_callback (gchar           *proc_name,
  346.         gchar           *scheme_proc_name,
  347.         gchar           *proc_blurb,
  348.         gchar           *proc_help,
  349.         gchar           *proc_author,
  350.         gchar           *proc_copyright,
  351.         gchar           *proc_date,
  352.         GimpPDBProcType  proc_type,
  353.         gint             nparams,
  354.         gint             nreturn_vals,
  355.         GimpParamDef    *params,
  356.         GimpParamDef    *return_vals)
  357. {
  358.   gint i;
  359.   GString *text;
  360.  
  361.   if (proc_name == NULL) 
  362.     return;
  363.   
  364.   text = g_string_new ("(");
  365.   text = g_string_append (text, scheme_proc_name);
  366.   for (i=0; i<nparams; i++) 
  367.     {
  368.       text = g_string_append_c (text, ' ');
  369.       text = g_string_append (text, params[i].name);
  370.     }
  371.   text = g_string_append_c (text, ')');
  372.  
  373.   gtk_entry_set_text (GTK_ENTRY (cint.cc), text->str);
  374.   g_string_free (text, TRUE);
  375. }
  376.  
  377. static void
  378. script_fu_browse_callback (GtkWidget *widget,
  379.                gpointer   data)
  380. {
  381.   gtk_quit_add_destroy (1, (GtkObject*) gimp_db_browser (apply_callback));
  382. }
  383.  
  384. static gint
  385. script_fu_console_scroll_end (gpointer data)
  386. {
  387.   /* The Text widget in 1.0.1 doesn't like being scrolled before
  388.    * it is size-allocated, so we wait for it
  389.    */
  390.   if ((cint.console->allocation.width > 1) && 
  391.       (cint.console->allocation.height > 1))
  392.     {
  393.       cint.vadj->value = cint.vadj->upper - cint.vadj->page_size;
  394.       gtk_signal_emit_by_name (GTK_OBJECT (cint.vadj), "changed");
  395.     }
  396.   else
  397.     gtk_idle_add (script_fu_console_scroll_end, NULL);
  398.   
  399.   return FALSE;
  400. }
  401.  
  402. static gboolean
  403. script_fu_siod_read (GIOChannel  *channel,
  404.              GIOCondition cond,
  405.              gpointer     data)
  406. {
  407.   int count;
  408.   static int hack = 0;
  409.   GIOError error;
  410.  
  411.   count = 0;
  412.   error = g_io_channel_read (channel, read_buffer, BUFSIZE - 1, &count);
  413.  
  414.   if (error == G_IO_ERROR_NONE)
  415.     {
  416. #ifndef G_OS_WIN32
  417.       /* Is this needed any longer on Unix? */
  418.       if (!hack) /* this is a stupid hack, but as of 10/27/98
  419.          * the script-fu-console will hang on my system without it.
  420.          * the real cause of this needs to be tracked down.
  421.          * posibly a problem with the text widget, or the
  422.          * signal handlers not getting fully initialized or...
  423.          * no reports of hangs on other platforms, could just be a
  424.          * problem with my system.
  425.          */
  426.       {
  427.     hack = 1;
  428.     return TRUE;
  429.       }
  430. #endif
  431.       read_buffer[count] = '\0';
  432.       gtk_text_freeze (GTK_TEXT (cint.console));
  433.       gtk_text_insert (GTK_TEXT (cint.console), cint.font_weak, NULL, NULL,
  434.                read_buffer, -1);
  435.       gtk_text_thaw (GTK_TEXT (cint.console));
  436.  
  437.       script_fu_console_scroll_end (NULL);
  438.     }
  439.   return TRUE;
  440. }
  441.  
  442. static gint
  443. script_fu_cc_is_empty (void)
  444. {
  445.   char *str;
  446.  
  447.   if ((str = gtk_entry_get_text (GTK_ENTRY (cint.cc))) == NULL)
  448.     return TRUE;
  449.  
  450.   while (*str)
  451.     {
  452.       if (*str != ' ' && *str != '\t' && *str != '\n')
  453.     return FALSE;
  454.  
  455.       str ++;
  456.     }
  457.  
  458.   return TRUE;
  459. }
  460.  
  461. static gint
  462. script_fu_cc_key_function (GtkWidget   *widget,
  463.                GdkEventKey *event,
  464.                gpointer     data)
  465. {
  466.   GList *list;
  467.   int direction = 0;
  468.  
  469.   switch (event->keyval)
  470.     {
  471.     case GDK_Return:
  472.       gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
  473.  
  474.       if (script_fu_cc_is_empty ())
  475.     return TRUE;
  476.  
  477.       list = g_list_nth (history, (g_list_length (history) - 1));
  478.       if (list->data)
  479.     g_free (list->data);
  480.       list->data = g_strdup (gtk_entry_get_text (GTK_ENTRY (cint.cc)));
  481.  
  482.       gtk_text_freeze (GTK_TEXT (cint.console));
  483.       gtk_text_insert (GTK_TEXT (cint.console), cint.font_strong, NULL, NULL, "=> ", -1);
  484.       gtk_text_insert (GTK_TEXT (cint.console), cint.font, NULL, NULL,
  485.                gtk_entry_get_text (GTK_ENTRY (cint.cc)), -1);
  486.       gtk_text_insert (GTK_TEXT (cint.console), cint.font, NULL, NULL, "\n\n", -1);
  487.       gtk_text_thaw (GTK_TEXT (cint.console));
  488.  
  489.       cint.vadj->value = cint.vadj->upper - cint.vadj->page_size;
  490.       gtk_signal_emit_by_name (GTK_OBJECT (cint.vadj), "changed");
  491.  
  492.       gtk_entry_set_text (GTK_ENTRY (cint.cc), "");
  493.       gdk_flush ();
  494.  
  495.       repl_c_string ((char *) list->data, 0, 0, 1);
  496.       gimp_displays_flush ();
  497.  
  498.       history = g_list_append (history, NULL);
  499.       if (history_len == history_max)
  500.     {
  501.       history = g_list_remove (history, history->data);
  502.       if (history->data)
  503.         g_free (history->data);
  504.     }
  505.       else
  506.     history_len++;
  507.       history_cur = g_list_length (history) - 1;
  508.  
  509.       return TRUE;
  510.       break;
  511.  
  512.     case GDK_KP_Up:
  513.     case GDK_Up:
  514.       gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
  515.       direction = -1;
  516.       break;
  517.  
  518.     case GDK_KP_Down:
  519.     case GDK_Down:
  520.       gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
  521.       direction = 1;
  522.       break;
  523.  
  524.     case GDK_P:
  525.     case GDK_p:
  526.       if (event->state & GDK_CONTROL_MASK)
  527.     {
  528.       gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
  529.       direction = -1;
  530.     }
  531.       break;
  532.  
  533.     case GDK_N:
  534.     case GDK_n:
  535.       if (event->state & GDK_CONTROL_MASK)
  536.     {
  537.       gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
  538.       direction = 1;
  539.     }
  540.       break;
  541.  
  542.     default:
  543.       break;
  544.     }
  545.  
  546.   if (direction)
  547.     {
  548.       /*  Make sure we keep track of the current one  */
  549.       if (history_cur == g_list_length (history) - 1)
  550.     {
  551.       list = g_list_nth (history, history_cur);
  552.       if (list->data)
  553.         g_free (list->data);
  554.       list->data = g_strdup (gtk_entry_get_text (GTK_ENTRY (cint.cc)));
  555.     }
  556.  
  557.       history_cur += direction;
  558.       if (history_cur < 0)
  559.     history_cur = 0;
  560.       if (history_cur >= history_len)
  561.     history_cur = history_len - 1;
  562.  
  563.       gtk_entry_set_text (GTK_ENTRY (cint.cc), (char *) (g_list_nth (history, history_cur))->data);
  564.  
  565.       return TRUE;
  566.     }
  567.  
  568.   return FALSE;
  569. }
  570.  
  571.  
  572. static FILE *
  573. script_fu_open_siod_console (void)
  574. {
  575.   if (siod_output == stdout)
  576.     {
  577.       if (pipe (siod_output_pipe))
  578.     {
  579.       gimp_message (_("Unable to open SIOD output pipe"));
  580.     }
  581.       else if ((siod_output = fdopen (siod_output_pipe [1], "w")) == NULL)
  582.     {
  583.       gimp_message (_("Unable to open a stream on the SIOD output pipe"));
  584.       siod_output = stdout;
  585.     }
  586.       else
  587.     {
  588.       siod_verbose_level = 2;
  589.       print_welcome ();
  590.     }
  591.     }
  592.  
  593.   return siod_output;
  594. }
  595.  
  596. static void
  597. script_fu_close_siod_console (void)
  598. {
  599.   if (siod_output != stdout)
  600.     fclose (siod_output);
  601.   close (siod_output_pipe[0]);
  602.   close (siod_output_pipe[1]);
  603. }
  604.  
  605. void
  606. script_fu_eval_run (char     *name,
  607.             int       nparams,
  608.             GimpParam   *params,
  609.             int      *nreturn_vals,
  610.             GimpParam  **return_vals)
  611. {
  612.   static GimpParam values[1];
  613.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  614.   GimpRunModeType run_mode;
  615.  
  616.   run_mode = params[0].data.d_int32;
  617.  
  618.   switch (run_mode)
  619.     {
  620.     case GIMP_RUN_NONINTERACTIVE:
  621.       if (repl_c_string (params[1].data.d_string, 0, 0, 1) != 0)
  622.     status = GIMP_PDB_EXECUTION_ERROR;
  623.       break;
  624.  
  625.     case GIMP_RUN_INTERACTIVE:
  626.     case GIMP_RUN_WITH_LAST_VALS:
  627.       status = GIMP_PDB_CALLING_ERROR;
  628.       gimp_message (_("Script-Fu evaluate mode allows only noninteractive invocation"));
  629.       break;
  630.  
  631.     default:
  632.       break;
  633.     }
  634.  
  635.   *nreturn_vals = 1;
  636.   *return_vals = values;
  637.  
  638.   values[0].type = GIMP_PDB_STATUS;
  639.   values[0].data.d_status = status;
  640. }
  641.