diff options
Diffstat (limited to '')
-rw-r--r-- | app/pdb/gimppdb-query.c | 649 |
1 files changed, 649 insertions, 0 deletions
diff --git a/app/pdb/gimppdb-query.c b/app/pdb/gimppdb-query.c new file mode 100644 index 0000000..00689fa --- /dev/null +++ b/app/pdb/gimppdb-query.c @@ -0,0 +1,649 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995-2003 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 <stdlib.h> +#include <string.h> + +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <gegl.h> + +#include "libgimpbase/gimpbase.h" + +#include "pdb-types.h" + +#include "core/gimpparamspecs-desc.h" + +#include "gimppdb.h" +#include "gimppdb-query.h" +#include "gimppdberror.h" +#include "gimp-pdb-compat.h" +#include "gimpprocedure.h" + +#include "gimp-intl.h" + + +#define PDB_REGEX_FLAGS (G_REGEX_CASELESS | G_REGEX_OPTIMIZE) + +#define COMPAT_BLURB "This procedure is deprecated! Use '%s' instead." + + +typedef struct _PDBDump PDBDump; + +struct _PDBDump +{ + GimpPDB *pdb; + GOutputStream *output; + GError *error; + + gboolean dumping_compat; +}; + +typedef struct _PDBQuery PDBQuery; + +struct _PDBQuery +{ + GimpPDB *pdb; + + GRegex *name_regex; + GRegex *blurb_regex; + GRegex *help_regex; + GRegex *author_regex; + GRegex *copyright_regex; + GRegex *date_regex; + GRegex *proc_type_regex; + + gchar **list_of_procs; + gint num_procs; + gboolean querying_compat; +}; + +typedef struct _PDBStrings PDBStrings; + +struct _PDBStrings +{ + gboolean compat; + + gchar *blurb; + gchar *help; + gchar *author; + gchar *copyright; + gchar *date; +}; + + +/* local function prototypes */ + +static void gimp_pdb_query_entry (gpointer key, + gpointer value, + gpointer user_data); +static void gimp_pdb_print_entry (gpointer key, + gpointer value, + gpointer user_data); +static void gimp_pdb_get_strings (PDBStrings *strings, + GimpProcedure *procedure, + gboolean compat); +static void gimp_pdb_free_strings (PDBStrings *strings); + + +/* public functions */ + +gboolean +gimp_pdb_dump (GimpPDB *pdb, + GFile *file, + GError **error) +{ + PDBDump pdb_dump = { 0, }; + + g_return_val_if_fail (GIMP_IS_PDB (pdb), FALSE); + g_return_val_if_fail (G_IS_FILE (file), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + pdb_dump.pdb = pdb; + pdb_dump.output = G_OUTPUT_STREAM (g_file_replace (file, + NULL, FALSE, + G_FILE_CREATE_NONE, + NULL, error)); + if (! pdb_dump.output) + return FALSE; + + pdb_dump.dumping_compat = FALSE; + + g_hash_table_foreach (pdb->procedures, + gimp_pdb_print_entry, + &pdb_dump); + + pdb_dump.dumping_compat = TRUE; + + g_hash_table_foreach (pdb->compat_proc_names, + gimp_pdb_print_entry, + &pdb_dump); + + if (pdb_dump.error) + { + GCancellable *cancellable = g_cancellable_new (); + + g_set_error (error, pdb_dump.error->domain, pdb_dump.error->code, + _("Writing PDB file '%s' failed: %s"), + gimp_file_get_utf8_name (file), pdb_dump.error->message); + g_clear_error (&pdb_dump.error); + + /* Cancel the overwrite initiated by g_file_replace(). */ + g_cancellable_cancel (cancellable); + g_output_stream_close (pdb_dump.output, cancellable, NULL); + g_object_unref (cancellable); + g_object_unref (pdb_dump.output); + + return FALSE; + } + + g_object_unref (pdb_dump.output); + + return TRUE; +} + +gboolean +gimp_pdb_query (GimpPDB *pdb, + const gchar *name, + const gchar *blurb, + const gchar *help, + const gchar *author, + const gchar *copyright, + const gchar *date, + const gchar *proc_type, + gint *num_procs, + gchar ***procs, + GError **error) +{ + PDBQuery pdb_query = { 0, }; + gboolean success = FALSE; + + g_return_val_if_fail (GIMP_IS_PDB (pdb), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + g_return_val_if_fail (blurb != NULL, FALSE); + g_return_val_if_fail (help != NULL, FALSE); + g_return_val_if_fail (author != NULL, FALSE); + g_return_val_if_fail (copyright != NULL, FALSE); + g_return_val_if_fail (date != NULL, FALSE); + g_return_val_if_fail (proc_type != NULL, FALSE); + g_return_val_if_fail (num_procs != NULL, FALSE); + g_return_val_if_fail (procs != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + *num_procs = 0; + *procs = NULL; + + pdb_query.name_regex = g_regex_new (name, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.name_regex) + goto cleanup; + + pdb_query.blurb_regex = g_regex_new (blurb, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.blurb_regex) + goto cleanup; + + pdb_query.help_regex = g_regex_new (help, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.help_regex) + goto cleanup; + + pdb_query.author_regex = g_regex_new (author, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.author_regex) + goto cleanup; + + pdb_query.copyright_regex = g_regex_new (copyright, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.copyright_regex) + goto cleanup; + + pdb_query.date_regex = g_regex_new (date, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.date_regex) + goto cleanup; + + pdb_query.proc_type_regex = g_regex_new (proc_type, PDB_REGEX_FLAGS, 0, error); + if (! pdb_query.proc_type_regex) + goto cleanup; + + success = TRUE; + + pdb_query.pdb = pdb; + pdb_query.list_of_procs = NULL; + pdb_query.num_procs = 0; + pdb_query.querying_compat = FALSE; + + g_hash_table_foreach (pdb->procedures, + gimp_pdb_query_entry, &pdb_query); + + pdb_query.querying_compat = TRUE; + + g_hash_table_foreach (pdb->compat_proc_names, + gimp_pdb_query_entry, &pdb_query); + + cleanup: + + if (pdb_query.proc_type_regex) + g_regex_unref (pdb_query.proc_type_regex); + + if (pdb_query.date_regex) + g_regex_unref (pdb_query.date_regex); + + if (pdb_query.copyright_regex) + g_regex_unref (pdb_query.copyright_regex); + + if (pdb_query.author_regex) + g_regex_unref (pdb_query.author_regex); + + if (pdb_query.help_regex) + g_regex_unref (pdb_query.help_regex); + + if (pdb_query.blurb_regex) + g_regex_unref (pdb_query.blurb_regex); + + if (pdb_query.name_regex) + g_regex_unref (pdb_query.name_regex); + + if (success) + { + *num_procs = pdb_query.num_procs; + *procs = pdb_query.list_of_procs; + } + + return success; +} + +gboolean +gimp_pdb_proc_info (GimpPDB *pdb, + const gchar *proc_name, + gchar **blurb, + gchar **help, + gchar **author, + gchar **copyright, + gchar **date, + GimpPDBProcType *proc_type, + gint *num_args, + gint *num_values, + GError **error) +{ + GimpProcedure *procedure; + PDBStrings strings; + + g_return_val_if_fail (GIMP_IS_PDB (pdb), FALSE); + g_return_val_if_fail (proc_name != NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + procedure = gimp_pdb_lookup_procedure (pdb, proc_name); + + if (procedure) + { + gimp_pdb_get_strings (&strings, procedure, FALSE); + } + else + { + const gchar *compat_name; + + compat_name = gimp_pdb_lookup_compat_proc_name (pdb, proc_name); + + if (compat_name) + { + procedure = gimp_pdb_lookup_procedure (pdb, compat_name); + + if (procedure) + gimp_pdb_get_strings (&strings, procedure, TRUE); + } + } + + if (procedure) + { + *blurb = strings.compat ? strings.blurb : g_strdup (strings.blurb); + *help = strings.compat ? strings.help : g_strdup (strings.help); + *author = strings.compat ? strings.author : g_strdup (strings.author); + *copyright = strings.compat ? strings.copyright : g_strdup (strings.copyright); + *date = strings.compat ? strings.date : g_strdup (strings.date); + *proc_type = procedure->proc_type; + *num_args = procedure->num_args; + *num_values = procedure->num_values; + + return TRUE; + } + + g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_PROCEDURE_NOT_FOUND, + _("Procedure '%s' not found"), proc_name); + + return FALSE; +} + + +/* private functions */ + +static gboolean +match_string (GRegex *regex, + const gchar *string) +{ + if (! string) + string = ""; + + return g_regex_match (regex, string, 0, NULL); +} + +static void +gimp_pdb_query_entry (gpointer key, + gpointer value, + gpointer user_data) +{ + PDBQuery *pdb_query = user_data; + GList *list; + GimpProcedure *procedure; + const gchar *proc_name; + PDBStrings strings; + GEnumClass *enum_class; + GimpEnumDesc *type_desc; + + proc_name = key; + + if (pdb_query->querying_compat) + list = g_hash_table_lookup (pdb_query->pdb->procedures, value); + else + list = value; + + if (! list) + return; + + procedure = list->data; + + gimp_pdb_get_strings (&strings, procedure, pdb_query->querying_compat); + + enum_class = g_type_class_ref (GIMP_TYPE_PDB_PROC_TYPE); + type_desc = gimp_enum_get_desc (enum_class, procedure->proc_type); + g_type_class_unref (enum_class); + + if (match_string (pdb_query->name_regex, proc_name) && + match_string (pdb_query->blurb_regex, strings.blurb) && + match_string (pdb_query->help_regex, strings.help) && + match_string (pdb_query->author_regex, strings.author) && + match_string (pdb_query->copyright_regex, strings.copyright) && + match_string (pdb_query->date_regex, strings.date) && + match_string (pdb_query->proc_type_regex, type_desc->value_desc)) + { + pdb_query->num_procs++; + pdb_query->list_of_procs = g_renew (gchar *, pdb_query->list_of_procs, + pdb_query->num_procs); + pdb_query->list_of_procs[pdb_query->num_procs - 1] = g_strdup (proc_name); + } + + gimp_pdb_free_strings (&strings); +} + +/* #define DEBUG_OUTPUT 1 */ + +static void +output_string (GString *dest, + const gchar *string) +{ +#ifndef DEBUG_OUTPUT + g_string_append_printf (dest, "\""); +#endif + + if (string) + while (*string) + { + switch (*string) + { + case '\\' : g_string_append_printf (dest, "\\\\"); break; + case '\"' : g_string_append_printf (dest, "\\\""); break; + case '{' : g_string_append_printf (dest, "@{"); break; + case '@' : g_string_append_printf (dest, "@@"); break; + case '}' : g_string_append_printf (dest, "@}"); break; + + default: + g_string_append_printf (dest, "%c", *string); + } + string++; + } + +#ifndef DEBUG_OUTPUT + g_string_append_printf (dest, "\"\n"); +#endif +} + +static void +gimp_pdb_print_entry (gpointer key, + gpointer value, + gpointer user_data) +{ + PDBDump *pdb_dump = user_data; + GOutputStream *output = pdb_dump->output; + const gchar *proc_name; + GList *list; + GEnumClass *arg_class; + GEnumClass *proc_class; + GString *buf; + GString *string; + gint num = 0; + + if (pdb_dump->error) + return; + + proc_name = key; + + if (pdb_dump->dumping_compat) + list = g_hash_table_lookup (pdb_dump->pdb->procedures, value); + else + list = value; + + arg_class = g_type_class_ref (GIMP_TYPE_PDB_ARG_TYPE); + proc_class = g_type_class_ref (GIMP_TYPE_PDB_PROC_TYPE); + + buf = g_string_new (NULL); + string = g_string_new (NULL); + + for (; list; list = list->next) + { + GimpProcedure *procedure = list->data; + PDBStrings strings; + GEnumValue *arg_value; + GimpEnumDesc *type_desc; + gint i; + + num++; + + gimp_pdb_get_strings (&strings, procedure, pdb_dump->dumping_compat); + +#ifdef DEBUG_OUTPUT + g_string_append_printf (string, "("); +#else + g_string_append_printf (string, "(register-procedure "); +#endif + + if (num != 1) + { + g_string_printf (buf, "%s <%d>", proc_name, num); + output_string (string, buf->str); + } + else + { + output_string (string, proc_name); + } + + type_desc = gimp_enum_get_desc (proc_class, procedure->proc_type); + +#ifdef DEBUG_OUTPUT + + g_string_append_printf (string, " ("); + + for (i = 0; i < procedure->num_args; i++) + { + GParamSpec *pspec = procedure->args[i]; + GimpPDBArgType arg_type; + + arg_type = gimp_pdb_compat_arg_type_from_gtype (pspec->value_type); + + arg_value = g_enum_get_value (arg_class, arg_type); + + if (i > 0) + g_string_append_printf (string, " "); + + output_string (string, arg_value->value_name); + } + + g_string_append_printf (string, ") ("); + + for (i = 0; i < procedure->num_values; i++) + { + GParamSpec *pspec = procedure->values[i]; + GimpPDBArgType arg_type; + + arg_type = gimp_pdb_compat_arg_type_from_gtype (pspec->value_type); + + arg_value = g_enum_get_value (arg_class, arg_type); + + if (i > 0) + g_string_append_printf (string, " "); + + output_string (string, arg_value->value_name); + } + + g_string_append_printf (string, "))\n"); + +#else /* ! DEBUG_OUTPUT */ + + g_string_append_printf (string, " "); + output_string (string, strings.blurb); + + g_string_append_printf (string, " "); + output_string (string, strings.help); + + g_string_append_printf (string, " "); + output_string (string, strings.author); + + g_string_append_printf (string, " "); + output_string (string, strings.copyright); + + g_string_append_printf (string, " "); + output_string (string, strings.date); + + g_string_append_printf (string, " "); + output_string (string, type_desc->value_desc); + + g_string_append_printf (string, " ("); + + for (i = 0; i < procedure->num_args; i++) + { + GParamSpec *pspec = procedure->args[i]; + GimpPDBArgType arg_type; + gchar *desc = gimp_param_spec_get_desc (pspec); + + g_string_append_printf (string, "\n (\n"); + + arg_type = gimp_pdb_compat_arg_type_from_gtype (pspec->value_type); + + arg_value = g_enum_get_value (arg_class, arg_type); + + g_string_append_printf (string, " "); + output_string (string, g_param_spec_get_name (pspec)); + + g_string_append_printf (string, " "); + output_string (string, arg_value->value_name); + + g_string_append_printf (string, " "); + output_string (string, desc); + + g_free (desc); + + g_string_append_printf (string, " )"); + } + + g_string_append_printf (string, "\n )\n"); + + g_string_append_printf (string, " ("); + + for (i = 0; i < procedure->num_values; i++) + { + GParamSpec *pspec = procedure->values[i]; + GimpPDBArgType arg_type; + gchar *desc = gimp_param_spec_get_desc (pspec); + + g_string_append_printf (string, "\n (\n"); + + arg_type = gimp_pdb_compat_arg_type_from_gtype (pspec->value_type); + + arg_value = g_enum_get_value (arg_class, arg_type); + + g_string_append_printf (string, " "); + output_string (string, g_param_spec_get_name (pspec)); + + g_string_append_printf (string, " "); + output_string (string, arg_value->value_name); + + g_string_append_printf (string, " "); + output_string (string, desc); + + g_free (desc); + + g_string_append_printf (string, " )"); + } + + g_string_append_printf (string, "\n )"); + g_string_append_printf (string, "\n)\n"); + +#endif /* DEBUG_OUTPUT */ + + gimp_pdb_free_strings (&strings); + } + + g_output_stream_write_all (output, string->str, string->len, + NULL, NULL, &pdb_dump->error); + + g_string_free (string, TRUE); + g_string_free (buf, TRUE); + + g_type_class_unref (arg_class); + g_type_class_unref (proc_class); +} + +static void +gimp_pdb_get_strings (PDBStrings *strings, + GimpProcedure *procedure, + gboolean compat) +{ + strings->compat = compat; + + if (compat) + { + strings->blurb = g_strdup_printf (COMPAT_BLURB, + gimp_object_get_name (procedure)); + strings->help = g_strdup (strings->blurb); + strings->author = NULL; + strings->copyright = NULL; + strings->date = NULL; + } + else + { + strings->blurb = procedure->blurb; + strings->help = procedure->help; + strings->author = procedure->author; + strings->copyright = procedure->copyright; + strings->date = procedure->date; + } +} + +static void +gimp_pdb_free_strings (PDBStrings *strings) +{ + if (strings->compat) + { + g_free (strings->blurb); + g_free (strings->help); + } +} |