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.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-08  |  30.6 KB  |  1,137 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. #if HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27.  
  28. #include <gtk/gtk.h>
  29. #include <libgimp/gimp.h>
  30.  
  31. #include "siod.h"
  32. #include "script-fu-console.h"
  33. #include "script-fu-constants.h"
  34. #include "script-fu-scripts.h"
  35. #include "script-fu-server.h"
  36.  
  37. #include "script-fu-intl.h"
  38.  
  39. extern FILE *siod_output;
  40.  
  41. /* External functions
  42.  */
  43. extern void  gimp_extension_process (guint timeout);
  44. extern void  gimp_extension_ack     (void);
  45.  
  46. extern void  init_subrs   (void);
  47. extern void  init_trace   (void);
  48. extern void  init_regex   (void);
  49.  
  50. extern long  nlength      (LISP   obj);
  51. extern LISP  leval_define (LISP   args,
  52.                LISP   env);
  53.  
  54. extern void  fput_st      (FILE  *f,
  55.                gchar *st);
  56.  
  57. /* Declare local functions.
  58.  */
  59. static void  sfquit (void);
  60. static void  query  (void);
  61. static void  run    (gchar        *name,
  62.              gint          nparams,
  63.              GimpParam    *param,
  64.              gint         *nreturn_vals,
  65.              GimpParam   **return_vals);
  66.  
  67. static gint  init_interp              (void);
  68. static void  init_gimp                (void);
  69. static void  init_procedures          (void);
  70. static void  init_constants           (void);
  71. static void  convert_string           (gchar *str);
  72.  
  73. static gint  sputs_fcn                (gchar *st,
  74.                        void  *dest);
  75. static LISP  lprin1s                  (LISP   exp,
  76.                        gchar *dest);
  77.  
  78. static LISP  marshall_proc_db_call    (LISP a);
  79. static LISP  script_fu_register_call  (LISP a);
  80. static LISP  script_fu_quit_call      (LISP a);
  81.  
  82. static void  script_fu_auxillary_init (void);
  83. static void  script_fu_refresh_proc   (gchar      *name,
  84.                        gint        nparams,
  85.                        GimpParam  *params,
  86.                        gint       *nreturn_vals,
  87.                        GimpParam **return_vals);
  88.  
  89.  
  90. GimpPlugInInfo PLUG_IN_INFO =
  91. {
  92.   NULL,   /* init_proc  */
  93.   sfquit, /* quit_proc  */
  94.   query,  /* query_proc */
  95.   run,    /* run_proc   */
  96. };
  97.  
  98. static gchar *siod_argv[] =
  99. {
  100.   "siod",
  101.   "-h100000:10",
  102.   "-g0",
  103.   "-o1000",
  104.   "-s200000",
  105.   "-n2048",
  106.   "-v0",
  107. };
  108.  
  109. static gint script_fu_base = TRUE;
  110. extern gint server_mode;
  111.  
  112. gint script_fu_done = FALSE;  /*  declared extern in script-fu-server.c  */
  113.  
  114.  
  115. MAIN ()
  116.  
  117. static void
  118. sfquit (void)
  119. {
  120. }
  121.  
  122. static void
  123. query (void)
  124. {
  125.   static GimpParamDef console_args[] =
  126.   {
  127.     { GIMP_PDB_INT32,  "run_mode", "Interactive, [non-interactive]" }
  128.   };
  129.   static gint nconsole_args = sizeof (console_args) / sizeof (console_args[0]);
  130.  
  131.   static GimpParamDef eval_args[] =
  132.   {
  133.     { GIMP_PDB_INT32,  "run_mode", "[Interactive], non-interactive" },
  134.     { GIMP_PDB_STRING, "code",     "The code to evaluate" }
  135.   };
  136.   static gint neval_args = sizeof (eval_args) / sizeof (eval_args[0]);
  137.  
  138.   static GimpParamDef server_args[] =
  139.   {
  140.     { GIMP_PDB_INT32,  "run_mode", "[Interactive], non-interactive" },
  141.     { GIMP_PDB_INT32,  "port",     "The port on which to listen for requests" },
  142.     { GIMP_PDB_STRING, "logfile",  "The file to log server activity to" }
  143.   };
  144.   static gint nserver_args = sizeof (server_args) / sizeof (server_args[0]);
  145.  
  146.   gimp_plugin_domain_register ("gimp-script-fu", NULL);
  147.  
  148.   gimp_install_procedure ("extension_script_fu",
  149.               "A scheme interpreter for scripting GIMP operations",
  150.               "More help here later",
  151.               "Spencer Kimball & Peter Mattis",
  152.               "Spencer Kimball & Peter Mattis",
  153.               "1997",
  154.               NULL,
  155.               NULL,
  156.               GIMP_EXTENSION,
  157.               0, 0, NULL, NULL);
  158.  
  159.   gimp_install_procedure ("extension_script_fu_console",
  160.               "Provides a console mode for script-fu development",
  161.               "Provides an interface which allows interactive scheme development.",
  162.               "Spencer Kimball & Peter Mattis",
  163.               "Spencer Kimball & Peter Mattis",
  164.               "1997",
  165.               N_("<Toolbox>/Xtns/Script-Fu/Console..."),
  166.               NULL,
  167.               GIMP_EXTENSION,
  168.               nconsole_args, 0,
  169.               console_args, NULL);
  170.  
  171. #ifndef G_OS_WIN32
  172.   gimp_install_procedure ("extension_script_fu_server",
  173.               "Provides a server for remote script-fu operation",
  174.               "Provides a server for remote script-fu operation",
  175.               "Spencer Kimball & Peter Mattis",
  176.               "Spencer Kimball & Peter Mattis",
  177.               "1997",
  178.               N_("<Toolbox>/Xtns/Script-Fu/Server..."),
  179.               NULL,
  180.               GIMP_EXTENSION,
  181.               nserver_args, 0,
  182.               server_args, NULL);
  183. #endif
  184.  
  185.   gimp_install_procedure ("extension_script_fu_eval",
  186.               "Evaluate scheme code",
  187.               "Evaluate the code under the scheme interpeter (primarily for batch mode)",
  188.               "Manish Singh",
  189.               "Manish Singh",
  190.               "1998",
  191.               NULL,
  192.               NULL,
  193.               GIMP_EXTENSION,
  194.               neval_args, 0,
  195.               eval_args, NULL);
  196. }
  197.  
  198. static void
  199. run (gchar      *name,
  200.      gint        nparams,
  201.      GimpParam  *param,
  202.      gint       *nreturn_vals,
  203.      GimpParam **return_vals)
  204. {
  205.   siod_output = stdout;
  206.  
  207.   /*  Determine before we allow scripts to register themselves
  208.    *   whether this is the base, automatically installed script-fu extension
  209.    */
  210.   if (strcmp (name, "extension_script_fu") == 0)
  211.     {
  212.       /*  Setup auxillary temporary procedures for the base extension  */
  213.       script_fu_auxillary_init ();
  214.  
  215.       script_fu_base = TRUE;
  216.     }
  217.   else
  218.     script_fu_base = FALSE;
  219.  
  220.   /*  Init the interpreter  */
  221.   init_interp ();
  222.  
  223.   /*  Load all of the available scripts  */
  224.   script_fu_find_scripts ();
  225.  
  226.   /*
  227.    *  The main, automatically installed script fu extension.
  228.    *  For things like logos and effects that are runnable from GIMP menus.
  229.    */
  230.   if (strcmp (name, "extension_script_fu") == 0)
  231.     {
  232.       static GimpParam  values[1];
  233.       GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  234.  
  235.       /*  Acknowledge that the extension is properly initialized  */
  236.       gimp_extension_ack ();
  237.  
  238.       while (TRUE)
  239.     gimp_extension_process (0);
  240.  
  241.       *nreturn_vals = 1;
  242.       *return_vals  = values;
  243.  
  244.       values[0].type          = GIMP_PDB_STATUS;
  245.       values[0].data.d_status = status;
  246.     }
  247.   /*
  248.    *  The script-fu console for interactive SIOD development
  249.    */
  250.   else if (strcmp (name, "extension_script_fu_console") == 0)
  251.     {
  252.       script_fu_console_run (name, nparams, param, nreturn_vals, return_vals);
  253.     }
  254. #ifndef G_OS_WIN32
  255.   /*
  256.    *  The script-fu server for remote operation
  257.    */
  258.   else if (strcmp (name, "extension_script_fu_server") == 0)
  259.     {
  260.       script_fu_server_run (name, nparams, param, nreturn_vals, return_vals);
  261.     }
  262. #endif
  263.   /*
  264.    *  A non-interactive "console" (for batch mode)
  265.    */
  266.   else if (strcmp (name, "extension_script_fu_eval") == 0)
  267.     {
  268.       script_fu_eval_run (name, nparams, param, nreturn_vals, return_vals);
  269.     }
  270. }
  271.  
  272. static gint
  273. init_interp (void)
  274. {
  275.   process_cla (sizeof (siod_argv) / sizeof (char *), siod_argv, 1);
  276.  
  277.   init_storage ();
  278.  
  279.   init_subrs ();
  280.   init_trace ();
  281.   init_regex ();
  282.   init_gimp  ();
  283.  
  284.   return 0;
  285. }
  286.  
  287. static void
  288. init_gimp (void)
  289. {
  290.   init_procedures ();
  291.   init_constants ();
  292. }
  293.  
  294. static void
  295. init_procedures (void)
  296. {
  297.   gchar          **proc_list;
  298.   gchar           *proc_name;
  299.   gchar           *arg_name;
  300.   gchar           *proc_blurb;
  301.   gchar           *proc_help;
  302.   gchar           *proc_author;
  303.   gchar           *proc_copyright;
  304.   gchar           *proc_date;
  305.   GimpPDBProcType  proc_type;
  306.   gint             nparams;
  307.   gint             nreturn_vals;
  308.   GimpParamDef    *params;
  309.   GimpParamDef    *return_vals;
  310.   gint             num_procs;
  311.   gint             i;
  312.  
  313.   /*  register the database execution procedure  */
  314.   init_lsubr ("gimp-proc-db-call",  marshall_proc_db_call);
  315.   init_lsubr ("script-fu-register", script_fu_register_call);
  316.   init_lsubr ("script-fu-quit",     script_fu_quit_call);
  317.  
  318.   gimp_procedural_db_query (".*", ".*", ".*", ".*", ".*", ".*", ".*", 
  319.                 &num_procs, &proc_list);
  320.  
  321.   /*  Register each procedure as a scheme func  */
  322.   for (i = 0; i < num_procs; i++)
  323.     {
  324.       proc_name = g_strdup (proc_list[i]);
  325.  
  326.       /*  lookup the procedure  */
  327.       if (gimp_procedural_db_proc_info (proc_name, 
  328.                     &proc_blurb, 
  329.                     &proc_help, 
  330.                     &proc_author,
  331.                     &proc_copyright, 
  332.                     &proc_date, 
  333.                     &proc_type, 
  334.                     &nparams, &nreturn_vals,
  335.                     ¶ms, &return_vals))
  336.     {
  337.       LISP args = NIL;
  338.       LISP code = NIL;
  339.       gint j;
  340.  
  341.       /*  convert the names to scheme-like naming conventions  */
  342.       convert_string (proc_name);
  343.  
  344.       /*  create a new scheme func that calls gimp-proc-db-call  */
  345.       for (j = 0; j < nparams; j++)
  346.         {
  347.           arg_name = g_strdup (params[j].name);
  348.           convert_string (arg_name);
  349.           args = cons (cintern (arg_name), args);
  350.           code = cons (cintern (arg_name), code);
  351.         }
  352.  
  353.       /*  reverse the list  */
  354.       args = nreverse (args);
  355.       code = nreverse (code);
  356.  
  357.       /*  set the scheme-based procedure name  */
  358.       args = cons (cintern (proc_name), args);
  359.  
  360.       /*  set the acture pdb procedure name  */
  361.       code = cons (cons (cintern ("quote"), 
  362.                  cons (cintern (proc_list[i]), NIL)), 
  363.                code);
  364.       code = cons (cintern ("gimp-proc-db-call"), code);
  365.  
  366.       leval_define (cons (args, cons (code, NIL)), NIL);
  367.  
  368.       /*  free the queried information  */
  369.       g_free (proc_blurb);
  370.       g_free (proc_help);
  371.       g_free (proc_author);
  372.       g_free (proc_copyright);
  373.       g_free (proc_date);
  374.       gimp_destroy_paramdefs (params, nparams);
  375.       gimp_destroy_paramdefs (return_vals, nreturn_vals);
  376.     }
  377.     }
  378.  
  379.   g_free (proc_list);
  380. }
  381.  
  382. static void
  383. init_constants (void)
  384. {
  385.   gchar *gimp_plugin_dir;
  386.  
  387.   setvar (cintern ("gimp-data-dir"), 
  388.       strcons (-1, gimp_data_directory ()), NIL);
  389.  
  390.   gimp_plugin_dir = gimp_gimprc_query ("gimp_plugin_dir");
  391.   if (gimp_plugin_dir)
  392.     {
  393.       setvar (cintern ("gimp-plugin-dir"), 
  394.           strcons (-1, gimp_plugin_dir), NIL);
  395.       g_free (gimp_plugin_dir);
  396.     }
  397.   
  398.   /* Generated constants */
  399.   init_generated_constants ();
  400.  
  401.   /* These are for backwards compatibility; they should be removed sometime */
  402.   setvar (cintern ("NORMAL"),         flocons (GIMP_NORMAL_MODE),       NIL);
  403.   setvar (cintern ("DISSOLVE"),       flocons (GIMP_DISSOLVE_MODE),     NIL);
  404.   setvar (cintern ("BEHIND"),         flocons (GIMP_BEHIND_MODE),       NIL);
  405.   setvar (cintern ("MULTIPLY"),       flocons (GIMP_MULTIPLY_MODE),     NIL);
  406.   setvar (cintern ("SCREEN"),         flocons (GIMP_SCREEN_MODE),       NIL);
  407.   setvar (cintern ("OVERLAY"),        flocons (GIMP_OVERLAY_MODE),      NIL);
  408.   setvar (cintern ("DIFFERENCE"),     flocons (GIMP_DIFFERENCE_MODE),   NIL);
  409.   setvar (cintern ("ADDITION"),       flocons (GIMP_ADDITION_MODE),     NIL);
  410.   setvar (cintern ("SUBTRACT"),       flocons (GIMP_SUBTRACT_MODE),     NIL);
  411.   setvar (cintern ("DARKEN-ONLY"),    flocons (GIMP_DARKEN_ONLY_MODE),  NIL);
  412.   setvar (cintern ("LIGHTEN-ONLY"),   flocons (GIMP_LIGHTEN_ONLY_MODE), NIL);
  413.   setvar (cintern ("HUE"),            flocons (GIMP_HUE_MODE),          NIL);
  414.   setvar (cintern ("SATURATION"),     flocons (GIMP_SATURATION_MODE),   NIL);
  415.   setvar (cintern ("COLOR"),          flocons (GIMP_COLOR_MODE),        NIL);
  416.   setvar (cintern ("VALUE"),          flocons (GIMP_VALUE_MODE),        NIL);
  417.   setvar (cintern ("DIVIDE"),         flocons (GIMP_DIVIDE_MODE),       NIL);
  418.  
  419.   setvar (cintern ("BLUR"),           flocons (GIMP_BLUR_CONVOLVE),     NIL);
  420.   setvar (cintern ("SHARPEN"),        flocons (GIMP_SHARPEN_CONVOLVE),  NIL);
  421.  
  422.   setvar (cintern ("RGB_IMAGE"),      flocons (GIMP_RGB_IMAGE),         NIL);
  423.   setvar (cintern ("RGBA_IMAGE"),     flocons (GIMP_RGBA_IMAGE),        NIL);
  424.   setvar (cintern ("GRAY_IMAGE"),     flocons (GIMP_GRAY_IMAGE),        NIL);
  425.   setvar (cintern ("GRAYA_IMAGE"),    flocons (GIMP_GRAYA_IMAGE),       NIL);
  426.   setvar (cintern ("INDEXED_IMAGE"),  flocons (GIMP_INDEXED_IMAGE),     NIL);
  427.   setvar (cintern ("INDEXEDA_IMAGE"), flocons (GIMP_INDEXEDA_IMAGE),    NIL);
  428.  
  429.   /* Useful misc stuff */
  430.   setvar (cintern ("TRUE"),           flocons (TRUE),  NIL);
  431.   setvar (cintern ("FALSE"),          flocons (FALSE), NIL);
  432.  
  433.   /*  Script-fu types  */
  434.   setvar (cintern ("SF-IMAGE"),       flocons (SF_IMAGE),      NIL);
  435.   setvar (cintern ("SF-DRAWABLE"),    flocons (SF_DRAWABLE),   NIL);
  436.   setvar (cintern ("SF-LAYER"),       flocons (SF_LAYER),      NIL);
  437.   setvar (cintern ("SF-CHANNEL"),     flocons (SF_CHANNEL),    NIL);
  438.   setvar (cintern ("SF-COLOR"),       flocons (SF_COLOR),      NIL);
  439.   setvar (cintern ("SF-TOGGLE"),      flocons (SF_TOGGLE),     NIL);
  440.   setvar (cintern ("SF-VALUE"),       flocons (SF_VALUE),      NIL);
  441.   setvar (cintern ("SF-STRING"),      flocons (SF_STRING),     NIL);
  442.   setvar (cintern ("SF-FILENAME"),    flocons (SF_FILENAME),   NIL);
  443.   setvar (cintern ("SF-ADJUSTMENT"),  flocons (SF_ADJUSTMENT), NIL);
  444.   setvar (cintern ("SF-FONT"),        flocons (SF_FONT),       NIL);
  445.   setvar (cintern ("SF-PATTERN"),     flocons (SF_PATTERN),    NIL);
  446.   setvar (cintern ("SF-BRUSH"),       flocons (SF_BRUSH),      NIL);
  447.   setvar (cintern ("SF-GRADIENT"),    flocons (SF_GRADIENT),   NIL);
  448.   setvar (cintern ("SF-OPTION"),      flocons (SF_OPTION),     NIL);
  449.  
  450.   /* for SF_ADJUSTMENT */
  451.   setvar (cintern ("SF-SLIDER"),      flocons (SF_SLIDER),     NIL);
  452.   setvar (cintern ("SF-SPINNER"),     flocons (SF_SPINNER),    NIL);
  453. }
  454.  
  455. static void
  456. convert_string (gchar *str)
  457. {
  458.   while (*str)
  459.     {
  460.       if (*str == '_') *str = '-';
  461.       str++;
  462.     }
  463. }
  464.  
  465. static gint
  466. sputs_fcn (gchar *st,
  467.        void  *dest)
  468. {
  469.   strcpy (*((gchar**)dest), st);
  470.   *((gchar**)dest) += strlen (st);
  471.  
  472.   return (1);
  473. }
  474.  
  475. static LISP
  476. lprin1s (LISP   exp,
  477.      gchar *dest)
  478. {
  479.   struct gen_printio s;
  480.  
  481.   s.putc_fcn    = NULL;
  482.   s.puts_fcn    = sputs_fcn;
  483.   s.cb_argument = &dest;
  484.  
  485.   lprin1g (exp, &s);
  486.  
  487.   return (NIL);
  488. }
  489.  
  490.  
  491. static LISP
  492. marshall_proc_db_call (LISP a)
  493. {
  494.   GimpParam       *args;
  495.   GimpParam       *values = NULL;
  496.   gint             nvalues;
  497.   gchar           *proc_name;
  498.   gchar           *proc_blurb;
  499.   gchar           *proc_help;
  500.   gchar           *proc_author;
  501.   gchar           *proc_copyright;
  502.   gchar           *proc_date;
  503.   GimpPDBProcType  proc_type;
  504.   gint             nparams;
  505.   gint             nreturn_vals;
  506.   GimpParamDef    *params;
  507.   GimpParamDef    *return_vals;
  508.   gchar  error_str[256];
  509.   gint   i;
  510.   gint   success = TRUE;
  511.   LISP   color_list;
  512.   LISP   intermediate_val;
  513.   LISP   return_val = NIL;
  514.   gchar *string;
  515.   gint   string_len;
  516.   LISP   a_saved;
  517.  
  518.   /* Save a in case it is needed for an error message. */
  519.   a_saved = a;
  520.  
  521.   /*  Make sure there are arguments  */
  522.   if (a == NIL)
  523.     return my_err ("Procedure database argument marshaller was called with no arguments. "
  524.            "The procedure to be executed and the arguments it requires "
  525.            "(possibly none) must be specified.", NIL);
  526.  
  527.   /*  Derive the pdb procedure name from the argument 
  528.       or first argument of a list  */
  529.   if (TYPEP (a, tc_cons))
  530.     proc_name = get_c_string (car (a));
  531.   else
  532.     proc_name = get_c_string (a);
  533.  
  534.   /*  report the current command  */
  535.   script_fu_report_cc (proc_name);
  536.  
  537.   /*  Attempt to fetch the procedure from the database  */
  538.   if (! gimp_procedural_db_proc_info (proc_name, 
  539.                       &proc_blurb, 
  540.                       &proc_help, 
  541.                       &proc_author,
  542.                       &proc_copyright,
  543.                       &proc_date,
  544.                       &proc_type,
  545.                       &nparams, &nreturn_vals,
  546.                       ¶ms, &return_vals))
  547.     return my_err ("Invalid procedure name specified.", NIL);
  548.  
  549.  
  550.   /*  Check the supplied number of arguments  */
  551.   if ((nlength (a) - 1) != nparams)
  552.     {
  553.       g_snprintf (error_str, sizeof (error_str), 
  554.           "Invalid arguments supplied to %s--(# args: %ld, expecting: %d)",
  555.           proc_name, (nlength (a) - 1), nparams);
  556.       return my_err (error_str, NIL);
  557.     }
  558.  
  559.   /*  Marshall the supplied arguments  */
  560.   if (nparams)
  561.     args = g_new (GimpParam, nparams);
  562.   else
  563.     args = NULL;
  564.  
  565.   a = cdr (a);
  566.   for (i = 0; i < nparams; i++)
  567.     {
  568.       switch (params[i].type)
  569.     {
  570.     case GIMP_PDB_INT32:
  571.       if (!TYPEP (car (a), tc_flonum))
  572.         success = FALSE;
  573.       if (success)
  574.         {
  575.           args[i].type = GIMP_PDB_INT32;
  576.           args[i].data.d_int32 = get_c_long (car (a));
  577.         }
  578.       break;
  579.  
  580.     case GIMP_PDB_INT16:
  581.       if (!TYPEP (car (a), tc_flonum))
  582.         success = FALSE;
  583.       if (success)
  584.         {
  585.           args[i].type = GIMP_PDB_INT16;
  586.           args[i].data.d_int16 = (gint16) get_c_long (car (a));
  587.         }
  588.       break;
  589.  
  590.     case GIMP_PDB_INT8:
  591.       if (!TYPEP (car (a), tc_flonum))
  592.         success = FALSE;
  593.       if (success)
  594.         {
  595.           args[i].type = GIMP_PDB_INT8;
  596.           args[i].data.d_int8 = (gint8) get_c_long (car (a));
  597.         }
  598.       break;
  599.  
  600.     case GIMP_PDB_FLOAT:
  601.       if (!TYPEP (car (a), tc_flonum))
  602.         success = FALSE;
  603.       if (success)
  604.         {
  605.           args[i].type = GIMP_PDB_FLOAT;
  606.           args[i].data.d_float = get_c_double (car (a));
  607.         }
  608.       break;
  609.  
  610.     case GIMP_PDB_STRING:
  611.       if (!TYPEP (car (a), tc_string))
  612.         success = FALSE;
  613.       if (success)
  614.         {
  615.           args[i].type = GIMP_PDB_STRING;
  616.           args[i].data.d_string = get_c_string (car (a));
  617.         }
  618.       break;
  619.  
  620.     case GIMP_PDB_INT32ARRAY:
  621.       if (!TYPEP (car (a), tc_long_array))
  622.         success = FALSE;
  623.       if (success)
  624.         {
  625.           args[i].type = GIMP_PDB_INT32ARRAY;
  626.           args[i].data.d_int32array = 
  627.         (gint32*) (car (a))->storage_as.long_array.data;
  628.         }
  629.       break;
  630.  
  631.     case GIMP_PDB_INT16ARRAY:
  632.       if (!TYPEP (car (a), tc_long_array))
  633.         success = FALSE;
  634.       if (success)
  635.         {
  636.           args[i].type = GIMP_PDB_INT16ARRAY;
  637.           args[i].data.d_int16array = 
  638.         (gint16*) (car (a))->storage_as.long_array.data;
  639.         }
  640.       break;
  641.  
  642.     case GIMP_PDB_INT8ARRAY:
  643.       if (!TYPEP (car (a), tc_byte_array))
  644.         success = FALSE;
  645.       if (success)
  646.         {
  647.           args[i].type = GIMP_PDB_INT8ARRAY;
  648.           args[i].data.d_int8array = 
  649.         (gint8*) (car (a))->storage_as.string.data;
  650.         }
  651.       break;
  652.  
  653.     case GIMP_PDB_FLOATARRAY:
  654.       if (!TYPEP (car (a), tc_double_array))
  655.         success = FALSE;
  656.       if (success)
  657.         {
  658.           args[i].type = GIMP_PDB_FLOATARRAY;
  659.           args[i].data.d_floatarray = (car (a))->storage_as.double_array.data;
  660.         }
  661.       break;
  662.  
  663.     case GIMP_PDB_STRINGARRAY:
  664.       if (!TYPEP (car (a), tc_cons))
  665.         success = FALSE;
  666.       if (success)
  667.         {
  668.           args[i].type = GIMP_PDB_STRINGARRAY;
  669.  
  670.           /*  Set the array  */
  671.           {
  672.         gint j;
  673.         gint num_strings;
  674.         gchar **array;
  675.         LISP list;
  676.  
  677.         list = car (a);
  678.         num_strings = args[i - 1].data.d_int32;
  679.         if (nlength (list) != num_strings)
  680.           return my_err ("String array argument has incorrectly specified length", NIL);
  681.         array = args[i].data.d_stringarray = 
  682.           g_new (char *, num_strings);
  683.  
  684.         for (j = 0; j < num_strings; j++)
  685.           {
  686.             array[j] = get_c_string (car (list));
  687.             list = cdr (list);
  688.           }
  689.           }
  690.         }
  691.       break;
  692.  
  693.     case GIMP_PDB_COLOR:
  694.       if (!TYPEP (car (a), tc_cons))
  695.         success = FALSE;
  696.       if (success)
  697.         {
  698.           args[i].type = GIMP_PDB_COLOR;
  699.           color_list = car (a);
  700.           args[i].data.d_color.red = get_c_long (car (color_list));
  701.           color_list = cdr (color_list);
  702.           args[i].data.d_color.green = get_c_long (car (color_list));
  703.           color_list = cdr (color_list);
  704.           args[i].data.d_color.blue = get_c_long (car (color_list));
  705.         }
  706.       break;
  707.  
  708.     case GIMP_PDB_REGION:
  709.       return my_err ("Regions are currently unsupported as arguments", 
  710.              car (a));
  711.       break;
  712.  
  713.     case GIMP_PDB_DISPLAY:
  714.       if (!TYPEP (car (a), tc_flonum))
  715.         success = FALSE;
  716.       if (success)
  717.         {
  718.           args[i].type = GIMP_PDB_DISPLAY;
  719.           args[i].data.d_int32 = get_c_long (car (a));
  720.         }
  721.       break;
  722.  
  723.     case GIMP_PDB_IMAGE:
  724.       if (!TYPEP (car (a), tc_flonum))
  725.         success = FALSE;
  726.       if (success)
  727.         {
  728.           args[i].type = GIMP_PDB_IMAGE;
  729.           args[i].data.d_int32 = get_c_long (car (a));
  730.         }
  731.       break;
  732.  
  733.     case GIMP_PDB_LAYER:
  734.       if (!TYPEP (car (a), tc_flonum))
  735.         success = FALSE;
  736.       if (success)
  737.         {
  738.           args[i].type = GIMP_PDB_LAYER;
  739.           args[i].data.d_int32 = get_c_long (car (a));
  740.         }
  741.       break;
  742.  
  743.     case GIMP_PDB_CHANNEL:
  744.       if (!TYPEP (car (a), tc_flonum))
  745.         success = FALSE;
  746.       if (success)
  747.         {
  748.           args[i].type = GIMP_PDB_CHANNEL;
  749.           args[i].data.d_int32 = get_c_long (car (a));
  750.         }
  751.       break;
  752.  
  753.     case GIMP_PDB_DRAWABLE:
  754.       if (!TYPEP (car (a), tc_flonum))
  755.         success = FALSE;
  756.       if (success)
  757.         {
  758.           args[i].type = GIMP_PDB_DRAWABLE;
  759.           args[i].data.d_int32 = get_c_long (car (a));
  760.         }
  761.       break;
  762.  
  763.     case GIMP_PDB_SELECTION:
  764.       if (!TYPEP (car (a), tc_flonum))
  765.         success = FALSE;
  766.       if (success)
  767.         {
  768.           args[i].type = GIMP_PDB_SELECTION;
  769.           args[i].data.d_int32 = get_c_long (car (a));
  770.         }
  771.       break;
  772.  
  773.     case GIMP_PDB_BOUNDARY:
  774.       return my_err ("Boundaries are currently unsupported as arguments", 
  775.              car (a));
  776.       break;
  777.  
  778.     case GIMP_PDB_PATH:
  779.       return my_err ("Paths are currently unsupported as arguments", 
  780.              car (a));
  781.       break;
  782.  
  783.     case GIMP_PDB_PARASITE:
  784.       if (!TYPEP (car (a), tc_cons))
  785.         success = FALSE;
  786.       if (success)
  787.         {
  788.           args[i].type = GIMP_PDB_PARASITE;
  789.           /* parasite->name */
  790.           intermediate_val = car (a);
  791.           args[i].data.d_parasite.name = 
  792.         get_c_string (car (intermediate_val));
  793.           
  794.           /* parasite->flags */
  795.           intermediate_val = cdr (intermediate_val);
  796.           args[i].data.d_parasite.flags = get_c_long (car(intermediate_val));
  797.  
  798.           /* parasite->size */
  799.           intermediate_val = cdr (intermediate_val);
  800.           args[i].data.d_parasite.size =
  801.         (car (intermediate_val))->storage_as.string.dim;
  802.  
  803.           /* parasite->data */
  804.           args[i].data.d_parasite.data =
  805.         (void*) (car (intermediate_val))->storage_as.string.data;
  806.         }
  807.       break;
  808.  
  809.     case GIMP_PDB_STATUS:
  810.       return my_err ("Status is for return types, not arguments", car (a));
  811.       break;
  812.  
  813.     default:
  814.       return my_err ("Unknown argument type", NIL);
  815.     }
  816.  
  817.       a = cdr (a);
  818.     }
  819.  
  820.   if (success)
  821.     values = gimp_run_procedure2 (proc_name, &nvalues, nparams, args);
  822.   else
  823.     return my_err ("Invalid types specified for arguments", NIL);
  824.  
  825.   /*  Check the return status  */
  826.   if (! values)
  827.     {
  828.       strcpy (error_str, "Procedural database execution did not return a status:\n    ");
  829.       lprin1s (a_saved, error_str + strlen(error_str));
  830.       
  831.       return my_err (error_str, NIL);
  832.     }
  833.  
  834.   switch (values[0].data.d_status)
  835.     {
  836.     case GIMP_PDB_EXECUTION_ERROR:
  837.       strcpy (error_str, "Procedural database execution failed:\n    ");
  838.       lprin1s (a_saved, error_str + strlen(error_str));
  839.       return my_err (error_str, NIL);
  840.       break;
  841.  
  842.     case GIMP_PDB_CALLING_ERROR:
  843.       strcpy (error_str, "Procedural database execution failed on invalid input arguments:\n    ");
  844.       lprin1s (a_saved, error_str + strlen(error_str));
  845.       return my_err (error_str, NIL);
  846.       break;
  847.  
  848.     case GIMP_PDB_SUCCESS:
  849.       return_val = NIL;
  850.  
  851.       for (i = 0; i < nvalues - 1; i++)
  852.     {
  853.       switch (return_vals[i].type)
  854.         {
  855.         case GIMP_PDB_INT32:
  856.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  857.                  return_val);
  858.           break;
  859.  
  860.         case GIMP_PDB_INT16:
  861.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  862.                  return_val);
  863.           break;
  864.  
  865.         case GIMP_PDB_INT8:
  866.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  867.                  return_val);
  868.           break;
  869.  
  870.         case GIMP_PDB_FLOAT:
  871.           return_val = cons (flocons (values[i + 1].data.d_float), 
  872.                  return_val);
  873.           break;
  874.  
  875.         case GIMP_PDB_STRING:
  876.           string = (gchar *) values[i + 1].data.d_string;
  877.           string_len = strlen (string);
  878.           return_val = cons (strcons (string_len, string), return_val);
  879.           break;
  880.  
  881.         case GIMP_PDB_INT32ARRAY:
  882.           {
  883.         LISP array;
  884.         int j;
  885.  
  886.         array = arcons (tc_long_array, values[i].data.d_int32, 0);
  887.         for (j = 0; j < values[i].data.d_int32; j++)
  888.           {
  889.             array->storage_as.long_array.data[j] = 
  890.               values[i + 1].data.d_int32array[j];
  891.           }
  892.         return_val = cons (array, return_val);
  893.           }
  894.           break;
  895.  
  896.         case GIMP_PDB_INT16ARRAY:
  897.           return my_err ("Arrays are currently unsupported as return values", NIL);
  898.           break;
  899.  
  900.         case GIMP_PDB_INT8ARRAY:
  901.           {
  902.         LISP array;
  903.         int j;
  904.  
  905.         array = arcons (tc_byte_array, values[i].data.d_int32, 0);
  906.         for (j = 0; j < values[i].data.d_int32; j++)
  907.           {
  908.             array->storage_as.string.data[j] = 
  909.               values[i + 1].data.d_int8array[j];
  910.           }
  911.         return_val = cons (array, return_val);
  912.           }
  913.           break;
  914.  
  915.         case GIMP_PDB_FLOATARRAY:
  916.           {
  917.         LISP array;
  918.         int j;
  919.  
  920.         array = arcons (tc_double_array, values[i].data.d_int32, 0);
  921.         for (j = 0; j < values[i].data.d_int32; j++)
  922.           {
  923.             array->storage_as.double_array.data[j] = 
  924.               values[i + 1].data.d_floatarray[j];
  925.           }
  926.         return_val = cons (array, return_val);
  927.           }
  928.           break;
  929.  
  930.         case GIMP_PDB_STRINGARRAY:
  931.           /*  string arrays are always implemented such that the previous
  932.            *  return value contains the number of strings in the array
  933.            */
  934.           {
  935.         int j;
  936.         int num_strings = values[i].data.d_int32;
  937.         LISP string_array = NIL;
  938.         char **array = (char **) values[i + 1].data.d_stringarray;
  939.  
  940.         for (j = 0; j < num_strings; j++)
  941.           {
  942.             string_len = strlen (array[j]);
  943.             string_array = cons (strcons (string_len, array[j]), 
  944.                      string_array);
  945.           }
  946.  
  947.         return_val = cons (nreverse (string_array), return_val);
  948.           }
  949.           break;
  950.  
  951.         case GIMP_PDB_COLOR:
  952.           intermediate_val = cons (flocons ((int) values[i + 1].data.d_color.red),
  953.                        cons (flocons ((int) values[i + 1].data.d_color.green),
  954.                          cons (flocons ((int) values[i + 1].data.d_color.blue),
  955.                            NIL)));
  956.           return_val = cons (intermediate_val, return_val);
  957.           break;
  958.  
  959.         case GIMP_PDB_REGION:
  960.           return my_err ("Regions are currently unsupported as return values", NIL);
  961.           break;
  962.  
  963.         case GIMP_PDB_DISPLAY:
  964.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  965.                  return_val);
  966.           break;
  967.  
  968.         case GIMP_PDB_IMAGE:
  969.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  970.                  return_val);
  971.           break;
  972.  
  973.         case GIMP_PDB_LAYER:
  974.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  975.                  return_val);
  976.           break;
  977.  
  978.         case GIMP_PDB_CHANNEL:
  979.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  980.                  return_val);
  981.           break;
  982.  
  983.         case GIMP_PDB_DRAWABLE:
  984.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  985.                  return_val);
  986.           break;
  987.  
  988.         case GIMP_PDB_SELECTION:
  989.           return_val = cons (flocons (values[i + 1].data.d_int32), 
  990.                  return_val);
  991.           break;
  992.  
  993.         case GIMP_PDB_BOUNDARY:
  994.           return my_err ("Boundaries are currently unsupported as return values", NIL);
  995.           break;
  996.  
  997.         case GIMP_PDB_PATH:
  998.           return my_err ("Paths are currently unsupported as return values", NIL);
  999.           break;
  1000.  
  1001.         case GIMP_PDB_PARASITE:
  1002.           {
  1003.         LISP name, flags, data;
  1004.  
  1005.         if (values[i + 1].data.d_parasite.name == NULL)
  1006.           {
  1007.             return_val = my_err("Error: null parasite", NIL);
  1008.           }
  1009.         else
  1010.           {
  1011.             string_len = strlen (values[i + 1].data.d_parasite.name);
  1012.             name    = strcons (string_len,
  1013.                        values[i + 1].data.d_parasite.name);
  1014.             
  1015.             flags   = flocons (values[i + 1].data.d_parasite.flags);
  1016.             data    = arcons (tc_byte_array,
  1017.                       values[i+1].data.d_parasite.size, 0);
  1018.             memcpy(data->storage_as.string.data,
  1019.                values[i+1].data.d_parasite.data, 
  1020.                values[i+1].data.d_parasite.size); 
  1021.             
  1022.             intermediate_val = cons (name, 
  1023.                          cons(flags, cons(data, NIL)));
  1024.             return_val = cons (intermediate_val, return_val);
  1025.           }
  1026.           }
  1027.           break;
  1028.  
  1029.         case GIMP_PDB_STATUS:
  1030.           return my_err ("Procedural database execution returned multiple status values", NIL);
  1031.           break;
  1032.  
  1033.         default:
  1034.           return my_err ("Unknown return type", NIL);
  1035.         }
  1036.     }
  1037.       break;
  1038.  
  1039.     case GIMP_PDB_PASS_THROUGH:
  1040.     case GIMP_PDB_CANCEL:   /*  should we do something here?  */
  1041.       break;
  1042.     }
  1043.  
  1044.   /*  free up the executed procedure return values  */
  1045.   gimp_destroy_params (values, nvalues);
  1046.  
  1047.   /*  free up arguments and values  */
  1048.   g_free (args);
  1049.  
  1050.   /*  free the query information  */
  1051.   g_free (proc_blurb);
  1052.   g_free (proc_help);
  1053.   g_free (proc_author);
  1054.   g_free (proc_copyright);
  1055.   g_free (proc_date);
  1056.   g_free (params);
  1057.   g_free (return_vals);
  1058.  
  1059.   /*  reverse the return values  */
  1060.   return_val = nreverse (return_val);
  1061. #ifndef G_OS_WIN32
  1062.   /*  if we're in server mode, listen for additional commands for 10 ms  */
  1063.   if (server_mode)
  1064.     script_fu_server_listen (10);
  1065. #endif
  1066.  
  1067. #ifdef GDK_WINDOWING_WIN32
  1068.   /* This seems to help a lot on Windoze. */
  1069.   while (gtk_events_pending ())
  1070.     gtk_main_iteration ();
  1071. #endif
  1072.  
  1073.   return return_val;
  1074. }
  1075.  
  1076. static LISP
  1077. script_fu_register_call (LISP a)
  1078. {
  1079.   if (script_fu_base)
  1080.     return script_fu_add_script (a);
  1081.   else
  1082.     return NIL;
  1083. }
  1084.  
  1085. static LISP
  1086. script_fu_quit_call (LISP a)
  1087. {
  1088.   script_fu_done = TRUE;
  1089.  
  1090.   return NIL;
  1091. }
  1092.  
  1093. static void
  1094. script_fu_auxillary_init (void)
  1095. {
  1096.   static GimpParamDef args[] =
  1097.   {
  1098.     { GIMP_PDB_INT32, "run_mode", "[Interactive], non-interactive" }
  1099.   };
  1100.   static gint nargs = sizeof (args) / sizeof (args[0]);
  1101.  
  1102.   INIT_I18N();
  1103.  
  1104.   gimp_install_temp_proc ("script_fu_refresh",
  1105.               _("Re-read all available scripts"),
  1106.               _("Re-read all available scripts"),
  1107.               "Spencer Kimball & Peter Mattis",
  1108.               "Spencer Kimball & Peter Mattis",
  1109.               "1997",
  1110.               N_("<Toolbox>/Xtns/Script-Fu/Refresh"),
  1111.               NULL,
  1112.               GIMP_TEMPORARY,
  1113.               nargs, 0,
  1114.               args, NULL,
  1115.               script_fu_refresh_proc);
  1116. }
  1117.  
  1118. static void
  1119. script_fu_refresh_proc (gchar       *name,
  1120.             gint         nparams,
  1121.             GimpParam   *params,
  1122.             gint        *nreturn_vals,
  1123.             GimpParam  **return_vals)
  1124. {
  1125.   static GimpParam  values[1];
  1126.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  1127.  
  1128.   /*  Reload all of the available scripts  */
  1129.   script_fu_find_scripts ();
  1130.  
  1131.   *nreturn_vals = 1;
  1132.   *return_vals  = values;
  1133.  
  1134.   values[0].type          = GIMP_PDB_STATUS;
  1135.   values[0].data.d_status = status;
  1136. }
  1137.