564 lines
15 KiB
C
564 lines
15 KiB
C
/* PIKA - Photo and Image Kooker Application
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
*
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
* 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 "libpikabase/pikabase.h"
|
|
|
|
#include "pdb-types.h"
|
|
|
|
#include "core/pikaparamspecs-desc.h"
|
|
|
|
#include "pikapdb.h"
|
|
#include "pikapdb-query.h"
|
|
#include "pikapdberror.h"
|
|
#include "pikaprocedure.h"
|
|
|
|
#include "pika-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
|
|
{
|
|
PikaPDB *pdb;
|
|
GOutputStream *output;
|
|
GError *error;
|
|
|
|
gboolean dumping_compat;
|
|
};
|
|
|
|
typedef struct _PDBQuery PDBQuery;
|
|
|
|
struct _PDBQuery
|
|
{
|
|
PikaPDB *pdb;
|
|
|
|
GRegex *name_regex;
|
|
GRegex *blurb_regex;
|
|
GRegex *help_regex;
|
|
GRegex *authors_regex;
|
|
GRegex *copyright_regex;
|
|
GRegex *date_regex;
|
|
GRegex *proc_type_regex;
|
|
|
|
gchar **list_of_procs;
|
|
gboolean querying_compat;
|
|
};
|
|
|
|
typedef struct _PDBStrings PDBStrings;
|
|
|
|
struct _PDBStrings
|
|
{
|
|
gboolean compat;
|
|
|
|
gchar *blurb;
|
|
gchar *help;
|
|
gchar *authors;
|
|
gchar *copyright;
|
|
gchar *date;
|
|
};
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void pika_pdb_query_entry (gpointer key,
|
|
gpointer value,
|
|
gpointer user_data);
|
|
static void pika_pdb_print_entry (gpointer key,
|
|
gpointer value,
|
|
gpointer user_data);
|
|
static void pika_pdb_get_strings (PDBStrings *strings,
|
|
PikaProcedure *procedure,
|
|
gboolean compat);
|
|
static void pika_pdb_free_strings (PDBStrings *strings);
|
|
|
|
|
|
/* public functions */
|
|
|
|
gboolean
|
|
pika_pdb_dump (PikaPDB *pdb,
|
|
GFile *file,
|
|
GError **error)
|
|
{
|
|
PDBDump pdb_dump = { 0, };
|
|
|
|
g_return_val_if_fail (PIKA_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,
|
|
pika_pdb_print_entry,
|
|
&pdb_dump);
|
|
|
|
pdb_dump.dumping_compat = TRUE;
|
|
|
|
g_hash_table_foreach (pdb->compat_proc_names,
|
|
pika_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"),
|
|
pika_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
|
|
pika_pdb_query (PikaPDB *pdb,
|
|
const gchar *name,
|
|
const gchar *blurb,
|
|
const gchar *help,
|
|
const gchar *authors,
|
|
const gchar *copyright,
|
|
const gchar *date,
|
|
const gchar *proc_type,
|
|
gchar ***procs,
|
|
GError **error)
|
|
{
|
|
PDBQuery pdb_query = { 0, };
|
|
gboolean success = FALSE;
|
|
|
|
g_return_val_if_fail (PIKA_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 (authors != 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 (procs != NULL, FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
*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.authors_regex = g_regex_new (authors, PDB_REGEX_FLAGS, 0, error);
|
|
if (! pdb_query.authors_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 = g_new0 (gchar *, 1);
|
|
pdb_query.querying_compat = FALSE;
|
|
|
|
g_hash_table_foreach (pdb->procedures,
|
|
pika_pdb_query_entry, &pdb_query);
|
|
|
|
pdb_query.querying_compat = TRUE;
|
|
|
|
g_hash_table_foreach (pdb->compat_proc_names,
|
|
pika_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.authors_regex)
|
|
g_regex_unref (pdb_query.authors_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)
|
|
{
|
|
*procs = pdb_query.list_of_procs;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static gboolean
|
|
match_string (GRegex *regex,
|
|
const gchar *string)
|
|
{
|
|
if (! string)
|
|
string = "";
|
|
|
|
return g_regex_match (regex, string, 0, NULL);
|
|
}
|
|
|
|
static void
|
|
pika_pdb_query_entry (gpointer key,
|
|
gpointer value,
|
|
gpointer user_data)
|
|
{
|
|
PDBQuery *pdb_query = user_data;
|
|
GList *list;
|
|
PikaProcedure *procedure;
|
|
const gchar *proc_name;
|
|
PDBStrings strings;
|
|
GEnumClass *enum_class;
|
|
const PikaEnumDesc *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;
|
|
|
|
pika_pdb_get_strings (&strings, procedure, pdb_query->querying_compat);
|
|
|
|
enum_class = g_type_class_ref (PIKA_TYPE_PDB_PROC_TYPE);
|
|
type_desc = pika_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->authors_regex, strings.authors) &&
|
|
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))
|
|
{
|
|
guint num_procs = g_strv_length (pdb_query->list_of_procs);
|
|
|
|
pdb_query->list_of_procs = g_renew (gchar *, pdb_query->list_of_procs,
|
|
num_procs + 2);
|
|
pdb_query->list_of_procs[num_procs] = g_strdup (proc_name);
|
|
pdb_query->list_of_procs[num_procs + 1] = NULL;
|
|
}
|
|
|
|
pika_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
|
|
pika_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 *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;
|
|
|
|
proc_class = g_type_class_ref (PIKA_TYPE_PDB_PROC_TYPE);
|
|
|
|
buf = g_string_new (NULL);
|
|
string = g_string_new (NULL);
|
|
|
|
for (; list; list = list->next)
|
|
{
|
|
PikaProcedure *procedure = list->data;
|
|
PDBStrings strings;
|
|
const PikaEnumDesc *type_desc;
|
|
gint i;
|
|
|
|
num++;
|
|
|
|
pika_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 = pika_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];
|
|
|
|
if (i > 0)
|
|
g_string_append_printf (string, " ");
|
|
|
|
output_string (string, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
|
}
|
|
|
|
g_string_append_printf (string, ") (");
|
|
|
|
for (i = 0; i < procedure->num_values; i++)
|
|
{
|
|
GParamSpec *pspec = procedure->values[i];
|
|
|
|
if (i > 0)
|
|
g_string_append_printf (string, " ");
|
|
|
|
output_string (string, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
|
}
|
|
|
|
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.authors);
|
|
|
|
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];
|
|
gchar *desc = pika_param_spec_get_desc (pspec);
|
|
|
|
g_string_append_printf (string, "\n (\n");
|
|
|
|
g_string_append_printf (string, " ");
|
|
output_string (string, g_param_spec_get_name (pspec));
|
|
|
|
g_string_append_printf (string, " ");
|
|
output_string (string, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
|
|
|
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];
|
|
gchar *desc = pika_param_spec_get_desc (pspec);
|
|
|
|
g_string_append_printf (string, "\n (\n");
|
|
|
|
g_string_append_printf (string, " ");
|
|
output_string (string, g_param_spec_get_name (pspec));
|
|
|
|
g_string_append_printf (string, " ");
|
|
output_string (string, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
|
|
|
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 */
|
|
|
|
pika_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 (proc_class);
|
|
}
|
|
|
|
static void
|
|
pika_pdb_get_strings (PDBStrings *strings,
|
|
PikaProcedure *procedure,
|
|
gboolean compat)
|
|
{
|
|
strings->compat = compat;
|
|
|
|
if (compat)
|
|
{
|
|
strings->blurb = g_strdup_printf (COMPAT_BLURB,
|
|
pika_object_get_name (procedure));
|
|
strings->help = g_strdup (strings->blurb);
|
|
strings->authors = NULL;
|
|
strings->copyright = NULL;
|
|
strings->date = NULL;
|
|
}
|
|
else
|
|
{
|
|
strings->blurb = procedure->blurb;
|
|
strings->help = procedure->help;
|
|
strings->authors = procedure->authors;
|
|
strings->copyright = procedure->copyright;
|
|
strings->date = procedure->date;
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_pdb_free_strings (PDBStrings *strings)
|
|
{
|
|
if (strings->compat)
|
|
{
|
|
g_free (strings->blurb);
|
|
g_free (strings->help);
|
|
}
|
|
}
|