diff options
Diffstat (limited to 'plug-ins/script-fu/script-fu-script.c')
-rw-r--r-- | plug-ins/script-fu/script-fu-script.c | 780 |
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 = ¶ms[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 (¶m->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; +} |