summaryrefslogtreecommitdiffstats
path: root/plug-ins/script-fu/script-fu-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/script-fu/script-fu-script.c')
-rw-r--r--plug-ins/script-fu/script-fu-script.c780
1 files changed, 780 insertions, 0 deletions
diff --git a/plug-ins/script-fu/script-fu-script.c b/plug-ins/script-fu/script-fu-script.c
new file mode 100644
index 0000000..cd37163
--- /dev/null
+++ b/plug-ins/script-fu/script-fu-script.c
@@ -0,0 +1,780 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "tinyscheme/scheme-private.h"
+
+#include "script-fu-types.h"
+
+#include "script-fu-script.h"
+#include "script-fu-scripts.h"
+#include "script-fu-utils.h"
+
+#include "script-fu-intl.h"
+
+
+/*
+ * Local Functions
+ */
+
+static gboolean script_fu_script_param_init (SFScript *script,
+ gint nparams,
+ const GimpParam *params,
+ SFArgType type,
+ gint n);
+
+
+/*
+ * Function definitions
+ */
+
+SFScript *
+script_fu_script_new (const gchar *name,
+ const gchar *menu_label,
+ const gchar *blurb,
+ const gchar *author,
+ const gchar *copyright,
+ const gchar *date,
+ const gchar *image_types,
+ gint n_args)
+{
+ SFScript *script;
+
+ script = g_slice_new0 (SFScript);
+
+ script->name = g_strdup (name);
+ script->menu_label = g_strdup (menu_label);
+ script->blurb = g_strdup (blurb);
+ script->author = g_strdup (author);
+ script->copyright = g_strdup (copyright);
+ script->date = g_strdup (date);
+ script->image_types = g_strdup (image_types);
+
+ script->n_args = n_args;
+ script->args = g_new0 (SFArg, script->n_args);
+
+ return script;
+}
+
+void
+script_fu_script_free (SFScript *script)
+{
+ gint i;
+
+ g_return_if_fail (script != NULL);
+
+ g_free (script->name);
+ g_free (script->blurb);
+ g_free (script->menu_label);
+ g_free (script->author);
+ g_free (script->copyright);
+ g_free (script->date);
+ g_free (script->image_types);
+
+ for (i = 0; i < script->n_args; i++)
+ {
+ SFArg *arg = &script->args[i];
+
+ g_free (arg->label);
+
+ switch (arg->type)
+ {
+ case SF_IMAGE:
+ case SF_DRAWABLE:
+ case SF_LAYER:
+ case SF_CHANNEL:
+ case SF_VECTORS:
+ case SF_DISPLAY:
+ case SF_COLOR:
+ case SF_TOGGLE:
+ break;
+
+ case SF_VALUE:
+ case SF_STRING:
+ case SF_TEXT:
+ g_free (arg->default_value.sfa_value);
+ g_free (arg->value.sfa_value);
+ break;
+
+ case SF_ADJUSTMENT:
+ break;
+
+ case SF_FILENAME:
+ case SF_DIRNAME:
+ g_free (arg->default_value.sfa_file.filename);
+ g_free (arg->value.sfa_file.filename);
+ break;
+
+ case SF_FONT:
+ g_free (arg->default_value.sfa_font);
+ g_free (arg->value.sfa_font);
+ break;
+
+ case SF_PALETTE:
+ g_free (arg->default_value.sfa_palette);
+ g_free (arg->value.sfa_palette);
+ break;
+
+ case SF_PATTERN:
+ g_free (arg->default_value.sfa_pattern);
+ g_free (arg->value.sfa_pattern);
+ break;
+
+ case SF_GRADIENT:
+ g_free (arg->default_value.sfa_gradient);
+ g_free (arg->value.sfa_gradient);
+ break;
+
+ case SF_BRUSH:
+ g_free (arg->default_value.sfa_brush.name);
+ g_free (arg->value.sfa_brush.name);
+ break;
+
+ case SF_OPTION:
+ g_slist_free_full (arg->default_value.sfa_option.list,
+ (GDestroyNotify) g_free);
+ break;
+
+ case SF_ENUM:
+ g_free (arg->default_value.sfa_enum.type_name);
+ break;
+ }
+ }
+
+ g_free (script->args);
+
+ g_slice_free (SFScript, script);
+}
+
+void
+script_fu_script_install_proc (SFScript *script,
+ GimpRunProc run_proc)
+{
+ const gchar *menu_label = NULL;
+ GimpParamDef *args;
+ gint i;
+
+ g_return_if_fail (script != NULL);
+ g_return_if_fail (run_proc != NULL);
+
+ /* Allow scripts with no menus */
+ if (strncmp (script->menu_label, "<None>", 6) != 0)
+ menu_label = script->menu_label;
+
+ args = g_new0 (GimpParamDef, script->n_args + 1);
+
+ args[0].type = GIMP_PDB_INT32;
+ args[0].name = "run-mode";
+ args[0].description = "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }";
+
+ for (i = 0; i < script->n_args; i++)
+ {
+ GimpPDBArgType type = 0;
+ const gchar *name = NULL;
+
+ switch (script->args[i].type)
+ {
+ case SF_IMAGE:
+ type = GIMP_PDB_IMAGE;
+ name = "image";
+ break;
+
+ case SF_DRAWABLE:
+ type = GIMP_PDB_DRAWABLE;
+ name = "drawable";
+ break;
+
+ case SF_LAYER:
+ type = GIMP_PDB_LAYER;
+ name = "layer";
+ break;
+
+ case SF_CHANNEL:
+ type = GIMP_PDB_CHANNEL;
+ name = "channel";
+ break;
+
+ case SF_VECTORS:
+ type = GIMP_PDB_VECTORS;
+ name = "vectors";
+ break;
+
+ case SF_DISPLAY:
+ type = GIMP_PDB_DISPLAY;
+ name = "display";
+ break;
+
+ case SF_COLOR:
+ type = GIMP_PDB_COLOR;
+ name = "color";
+ break;
+
+ case SF_TOGGLE:
+ type = GIMP_PDB_INT32;
+ name = "toggle";
+ break;
+
+ case SF_VALUE:
+ type = GIMP_PDB_STRING;
+ name = "value";
+ break;
+
+ case SF_STRING:
+ case SF_TEXT:
+ type = GIMP_PDB_STRING;
+ name = "string";
+ break;
+
+ case SF_ADJUSTMENT:
+ type = GIMP_PDB_FLOAT;
+ name = "value";
+ break;
+
+ case SF_FILENAME:
+ type = GIMP_PDB_STRING;
+ name = "filename";
+ break;
+
+ case SF_DIRNAME:
+ type = GIMP_PDB_STRING;
+ name = "dirname";
+ break;
+
+ case SF_FONT:
+ type = GIMP_PDB_STRING;
+ name = "font";
+ break;
+
+ case SF_PALETTE:
+ type = GIMP_PDB_STRING;
+ name = "palette";
+ break;
+
+ case SF_PATTERN:
+ type = GIMP_PDB_STRING;
+ name = "pattern";
+ break;
+
+ case SF_BRUSH:
+ type = GIMP_PDB_STRING;
+ name = "brush";
+ break;
+
+ case SF_GRADIENT:
+ type = GIMP_PDB_STRING;
+ name = "gradient";
+ break;
+
+ case SF_OPTION:
+ type = GIMP_PDB_INT32;
+ name = "option";
+ break;
+
+ case SF_ENUM:
+ type = GIMP_PDB_INT32;
+ name = "enum";
+ break;
+ }
+
+ args[i + 1].type = type;
+ args[i + 1].name = (gchar *) name;
+ args[i + 1].description = script->args[i].label;
+ }
+
+ gimp_install_temp_proc (script->name,
+ script->blurb,
+ "",
+ script->author,
+ script->copyright,
+ script->date,
+ menu_label,
+ script->image_types,
+ GIMP_TEMPORARY,
+ script->n_args + 1, 0,
+ args, NULL,
+ run_proc);
+
+ g_free (args);
+}
+
+void
+script_fu_script_uninstall_proc (SFScript *script)
+{
+ g_return_if_fail (script != NULL);
+
+ gimp_uninstall_temp_proc (script->name);
+}
+
+gchar *
+script_fu_script_get_title (SFScript *script)
+{
+ gchar *title;
+ gchar *tmp;
+
+ g_return_val_if_fail (script != NULL, NULL);
+
+ /* strip mnemonics from the menupath */
+ title = gimp_strip_uline (script->menu_label);
+
+ /* if this looks like a full menu path, use only the last part */
+ if (title[0] == '<' && (tmp = strrchr (title, '/')) && tmp[1])
+ {
+ tmp = g_strdup (tmp + 1);
+
+ g_free (title);
+ title = tmp;
+ }
+
+ /* cut off ellipsis */
+ tmp = (strstr (title, "..."));
+ if (! tmp)
+ /* U+2026 HORIZONTAL ELLIPSIS */
+ tmp = strstr (title, "\342\200\246");
+
+ if (tmp && tmp == (title + strlen (title) - 3))
+ *tmp = '\0';
+
+ return title;
+}
+
+void
+script_fu_script_reset (SFScript *script,
+ gboolean reset_ids)
+{
+ gint i;
+
+ g_return_if_fail (script != NULL);
+
+ for (i = 0; i < script->n_args; i++)
+ {
+ SFArgValue *value = &script->args[i].value;
+ SFArgValue *default_value = &script->args[i].default_value;
+
+ switch (script->args[i].type)
+ {
+ case SF_IMAGE:
+ case SF_DRAWABLE:
+ case SF_LAYER:
+ case SF_CHANNEL:
+ case SF_VECTORS:
+ case SF_DISPLAY:
+ if (reset_ids)
+ value->sfa_image = default_value->sfa_image;
+ break;
+
+ case SF_COLOR:
+ value->sfa_color = default_value->sfa_color;
+ break;
+
+ case SF_TOGGLE:
+ value->sfa_toggle = default_value->sfa_toggle;
+ break;
+
+ case SF_VALUE:
+ case SF_STRING:
+ case SF_TEXT:
+ g_free (value->sfa_value);
+ value->sfa_value = g_strdup (default_value->sfa_value);
+ break;
+
+ case SF_ADJUSTMENT:
+ value->sfa_adjustment.value = default_value->sfa_adjustment.value;
+ break;
+
+ case SF_FILENAME:
+ case SF_DIRNAME:
+ g_free (value->sfa_file.filename);
+ value->sfa_file.filename = g_strdup (default_value->sfa_file.filename);
+ break;
+
+ case SF_FONT:
+ g_free (value->sfa_font);
+ value->sfa_font = g_strdup (default_value->sfa_font);
+ break;
+
+ case SF_PALETTE:
+ g_free (value->sfa_palette);
+ value->sfa_palette = g_strdup (default_value->sfa_palette);
+ break;
+
+ case SF_PATTERN:
+ g_free (value->sfa_pattern);
+ value->sfa_pattern = g_strdup (default_value->sfa_pattern);
+ break;
+
+ case SF_GRADIENT:
+ g_free (value->sfa_gradient);
+ value->sfa_gradient = g_strdup (default_value->sfa_gradient);
+ break;
+
+ case SF_BRUSH:
+ g_free (value->sfa_brush.name);
+ value->sfa_brush.name = g_strdup (default_value->sfa_brush.name);
+ value->sfa_brush.opacity = default_value->sfa_brush.opacity;
+ value->sfa_brush.spacing = default_value->sfa_brush.spacing;
+ value->sfa_brush.paint_mode = default_value->sfa_brush.paint_mode;
+ break;
+
+ case SF_OPTION:
+ value->sfa_option.history = default_value->sfa_option.history;
+ break;
+
+ case SF_ENUM:
+ value->sfa_enum.history = default_value->sfa_enum.history;
+ break;
+ }
+ }
+}
+
+gint
+script_fu_script_collect_standard_args (SFScript *script,
+ gint n_params,
+ const GimpParam *params)
+{
+ gint params_consumed = 0;
+
+ g_return_val_if_fail (script != NULL, 0);
+
+ /* the first parameter may be a DISPLAY id */
+ if (script_fu_script_param_init (script,
+ n_params, params, SF_DISPLAY,
+ params_consumed))
+ {
+ params_consumed++;
+ }
+
+ /* an IMAGE id may come first or after the DISPLAY id */
+ if (script_fu_script_param_init (script,
+ n_params, params, SF_IMAGE,
+ params_consumed))
+ {
+ params_consumed++;
+
+ /* and may be followed by a DRAWABLE, LAYER, CHANNEL or
+ * VECTORS id
+ */
+ if (script_fu_script_param_init (script,
+ n_params, params, SF_DRAWABLE,
+ params_consumed) ||
+ script_fu_script_param_init (script,
+ n_params, params, SF_LAYER,
+ params_consumed) ||
+ script_fu_script_param_init (script,
+ n_params, params, SF_CHANNEL,
+ params_consumed) ||
+ script_fu_script_param_init (script,
+ n_params, params, SF_VECTORS,
+ params_consumed))
+ {
+ params_consumed++;
+ }
+ }
+
+ return params_consumed;
+}
+
+gchar *
+script_fu_script_get_command (SFScript *script)
+{
+ GString *s;
+ gint i;
+
+ g_return_val_if_fail (script != NULL, NULL);
+
+ s = g_string_new ("(");
+ g_string_append (s, script->name);
+
+ for (i = 0; i < script->n_args; i++)
+ {
+ SFArgValue *arg_value = &script->args[i].value;
+
+ g_string_append_c (s, ' ');
+
+ switch (script->args[i].type)
+ {
+ case SF_IMAGE:
+ case SF_DRAWABLE:
+ case SF_LAYER:
+ case SF_CHANNEL:
+ case SF_VECTORS:
+ case SF_DISPLAY:
+ g_string_append_printf (s, "%d", arg_value->sfa_image);
+ break;
+
+ case SF_COLOR:
+ {
+ guchar r, g, b;
+
+ gimp_rgb_get_uchar (&arg_value->sfa_color, &r, &g, &b);
+ g_string_append_printf (s, "'(%d %d %d)",
+ (gint) r, (gint) g, (gint) b);
+ }
+ break;
+
+ case SF_TOGGLE:
+ g_string_append (s, arg_value->sfa_toggle ? "TRUE" : "FALSE");
+ break;
+
+ case SF_VALUE:
+ g_string_append (s, arg_value->sfa_value);
+ break;
+
+ case SF_STRING:
+ case SF_TEXT:
+ {
+ gchar *tmp;
+
+ tmp = script_fu_strescape (arg_value->sfa_value);
+ g_string_append_printf (s, "\"%s\"", tmp);
+ g_free (tmp);
+ }
+ break;
+
+ case SF_ADJUSTMENT:
+ {
+ gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_ascii_dtostr (buffer, sizeof (buffer),
+ arg_value->sfa_adjustment.value);
+ g_string_append (s, buffer);
+ }
+ break;
+
+ case SF_FILENAME:
+ case SF_DIRNAME:
+ {
+ gchar *tmp;
+
+ tmp = script_fu_strescape (arg_value->sfa_file.filename);
+ g_string_append_printf (s, "\"%s\"", tmp);
+ g_free (tmp);
+ }
+ break;
+
+ case SF_FONT:
+ g_string_append_printf (s, "\"%s\"", arg_value->sfa_font);
+ break;
+
+ case SF_PALETTE:
+ g_string_append_printf (s, "\"%s\"", arg_value->sfa_palette);
+ break;
+
+ case SF_PATTERN:
+ g_string_append_printf (s, "\"%s\"", arg_value->sfa_pattern);
+ break;
+
+ case SF_GRADIENT:
+ g_string_append_printf (s, "\"%s\"", arg_value->sfa_gradient);
+ break;
+
+ case SF_BRUSH:
+ {
+ gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_ascii_dtostr (buffer, sizeof (buffer),
+ arg_value->sfa_brush.opacity);
+ g_string_append_printf (s, "'(\"%s\" %s %d %d)",
+ arg_value->sfa_brush.name,
+ buffer,
+ arg_value->sfa_brush.spacing,
+ arg_value->sfa_brush.paint_mode);
+ }
+ break;
+
+ case SF_OPTION:
+ g_string_append_printf (s, "%d", arg_value->sfa_option.history);
+ break;
+
+ case SF_ENUM:
+ g_string_append_printf (s, "%d", arg_value->sfa_enum.history);
+ break;
+ }
+ }
+
+ g_string_append_c (s, ')');
+
+ return g_string_free (s, FALSE);
+}
+
+gchar *
+script_fu_script_get_command_from_params (SFScript *script,
+ const GimpParam *params)
+{
+ GString *s;
+ gint i;
+
+ g_return_val_if_fail (script != NULL, NULL);
+
+ s = g_string_new ("(");
+ g_string_append (s, script->name);
+
+ for (i = 0; i < script->n_args; i++)
+ {
+ const GimpParam *param = &params[i + 1];
+
+ g_string_append_c (s, ' ');
+
+ switch (script->args[i].type)
+ {
+ case SF_IMAGE:
+ case SF_DRAWABLE:
+ case SF_LAYER:
+ case SF_CHANNEL:
+ case SF_VECTORS:
+ case SF_DISPLAY:
+ g_string_append_printf (s, "%d", param->data.d_int32);
+ break;
+
+ case SF_COLOR:
+ {
+ guchar r, g, b;
+
+ gimp_rgb_get_uchar (&param->data.d_color, &r, &g, &b);
+ g_string_append_printf (s, "'(%d %d %d)",
+ (gint) r, (gint) g, (gint) b);
+ }
+ break;
+
+ case SF_TOGGLE:
+ g_string_append_printf (s, (param->data.d_int32 ? "TRUE" : "FALSE"));
+ break;
+
+ case SF_VALUE:
+ g_string_append (s, param->data.d_string);
+ break;
+
+ case SF_STRING:
+ case SF_TEXT:
+ case SF_FILENAME:
+ case SF_DIRNAME:
+ {
+ gchar *tmp;
+
+ tmp = script_fu_strescape (param->data.d_string);
+ g_string_append_printf (s, "\"%s\"", tmp);
+ g_free (tmp);
+ }
+ break;
+
+ case SF_ADJUSTMENT:
+ {
+ gchar buffer[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_ascii_dtostr (buffer, sizeof (buffer), param->data.d_float);
+ g_string_append (s, buffer);
+ }
+ break;
+
+ case SF_FONT:
+ case SF_PALETTE:
+ case SF_PATTERN:
+ case SF_GRADIENT:
+ case SF_BRUSH:
+ g_string_append_printf (s, "\"%s\"", param->data.d_string);
+ break;
+
+ case SF_OPTION:
+ case SF_ENUM:
+ g_string_append_printf (s, "%d", param->data.d_int32);
+ break;
+ }
+ }
+
+ g_string_append_c (s, ')');
+
+ return g_string_free (s, FALSE);
+}
+
+
+/*
+ * Local Functions
+ */
+
+static gboolean
+script_fu_script_param_init (SFScript *script,
+ gint nparams,
+ const GimpParam *params,
+ SFArgType type,
+ gint n)
+{
+ SFArg *arg = &script->args[n];
+
+ if (script->n_args > n && arg->type == type && nparams > n + 1)
+ {
+ switch (type)
+ {
+ case SF_IMAGE:
+ if (params[n + 1].type == GIMP_PDB_IMAGE)
+ {
+ arg->value.sfa_image = params[n + 1].data.d_image;
+ return TRUE;
+ }
+ break;
+
+ case SF_DRAWABLE:
+ if (params[n + 1].type == GIMP_PDB_DRAWABLE)
+ {
+ arg->value.sfa_drawable = params[n + 1].data.d_drawable;
+ return TRUE;
+ }
+ break;
+
+ case SF_LAYER:
+ if (params[n + 1].type == GIMP_PDB_LAYER)
+ {
+ arg->value.sfa_layer = params[n + 1].data.d_layer;
+ return TRUE;
+ }
+ break;
+
+ case SF_CHANNEL:
+ if (params[n + 1].type == GIMP_PDB_CHANNEL)
+ {
+ arg->value.sfa_channel = params[n + 1].data.d_channel;
+ return TRUE;
+ }
+ break;
+
+ case SF_VECTORS:
+ if (params[n + 1].type == GIMP_PDB_VECTORS)
+ {
+ arg->value.sfa_vectors = params[n + 1].data.d_vectors;
+ return TRUE;
+ }
+ break;
+
+ case SF_DISPLAY:
+ if (params[n + 1].type == GIMP_PDB_DISPLAY)
+ {
+ arg->value.sfa_display = params[n + 1].data.d_display;
+ return TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}