app/config/gimpconfig.[ch] app/config/gimpconfigwriter.[ch] added support

2003-06-23  Sven Neumann  <sven@gimp.org>

	* app/config/gimpconfig.[ch]
	* app/config/gimpconfigwriter.[ch]
	* app/config/gimpscanner.[ch]: added support for serializing to
	and deserializing from strings. Had to do some smaller changes to
	the GimpConfig API.

	* app/config/test-config.c: added a simple test for the new
	functions.

	* app/config/gimpconfig-dump.c
	* app/config/gimprc.c
	* app/core/gimp-documents.c
	* app/core/gimp-parasites.c
	* app/core/gimp-templates.c
	* app/core/gimpunits.c
	* app/gui/session.c
	* app/plug-in/plug-in-rc.c
	* app/tools/tool_options.c
	* app/widgets/gimpdevices.c: follow GimpConfig API changes.

	* libgimpbase/gimpparasite.[ch]: declared the return value of
	gimp_parasite_data() as gconstpointer.
This commit is contained in:
Sven Neumann 2003-06-23 22:02:56 +00:00 committed by Sven Neumann
parent dffe80c29a
commit f30586d112
29 changed files with 637 additions and 278 deletions

View File

@ -1,7 +1,31 @@
2003-06-23 Sven Neumann <sven@gimp.org>
* app/config/gimpconfig.[ch]
* app/config/gimpconfigwriter.[ch]
* app/config/gimpscanner.[ch]: added support for serializing to
and deserializing from strings. Had to do some smaller changes to
the GimpConfig API.
* app/config/test-config.c: added a simple test for the new
functions.
* app/config/gimpconfig-dump.c
* app/config/gimprc.c
* app/core/gimp-documents.c
* app/core/gimp-parasites.c
* app/core/gimp-templates.c
* app/core/gimpunits.c
* app/gui/session.c
* app/plug-in/plug-in-rc.c
* app/tools/tool_options.c
* app/widgets/gimpdevices.c: follow GimpConfig API changes.
* libgimpbase/gimpparasite.[ch]: declared the return value of
gimp_parasite_data() as gconstpointer.
2003-06-23 Henrik Brix Andersen <brix@gimp.org>
Added a per image configurable grid.
This fixes bug #65198
Added a per image configurable grid. This fixes bug #65198.
* app/core/Makefile.am
* app/core/core-types.h:

View File

@ -55,9 +55,11 @@ typedef enum
static gint dump_gimprc (DumpFormat format);
static void dump_gimprc_system (GObject *rc,
GimpConfigWriter *writer);
GimpConfigWriter *writer,
gint fd);
static void dump_gimprc_manpage (GObject *rc,
GimpConfigWriter *writer);
GimpConfigWriter *writer,
gint fd);
static gchar * dump_describe_param (GParamSpec *param_spec);
static void dump_with_linebreaks (gint fd,
const gchar *text);
@ -110,6 +112,7 @@ dump_gimprc (DumpFormat format)
{
GimpConfigWriter *writer;
GObject *rc;
gint fd = 1;
if (format == DUMP_NONE)
return EXIT_SUCCESS;
@ -120,7 +123,7 @@ dump_gimprc (DumpFormat format)
"module-load-inhibit", "foo", /* for completeness */
NULL);
writer = gimp_config_writer_new_from_fd (1);
writer = gimp_config_writer_new_fd (fd);
switch (format)
{
@ -133,10 +136,10 @@ dump_gimprc (DumpFormat format)
g_print ("\n");
break;
case DUMP_COMMENT:
dump_gimprc_system (rc, writer);
dump_gimprc_system (rc, writer, fd);
break;
case DUMP_MANPAGE:
dump_gimprc_manpage (rc, writer);
dump_gimprc_manpage (rc, writer, fd);
break;
default:
break;
@ -167,7 +170,8 @@ static const gchar *system_gimprc_header =
static void
dump_gimprc_system (GObject *rc,
GimpConfigWriter *writer)
GimpConfigWriter *writer,
gint fd)
{
GObjectClass *klass;
GParamSpec **property_specs;
@ -194,11 +198,10 @@ dump_gimprc_system (GObject *rc,
gimp_config_writer_comment (writer, comment);
g_free (comment);
write (writer->fd, "#\n", 2);
write (fd, "#\n", 2);
}
/* kids, don't try this at home! */
write (writer->fd, "# ", 2);
write (fd, "# ", 2);
gimp_config_serialize_property (rc, prop_spec, writer);
gimp_config_writer_linefeed (writer);
@ -296,14 +299,15 @@ static const gchar *man_page_footer =
static void
dump_gimprc_manpage (GObject *rc,
GimpConfigWriter *writer)
GimpConfigWriter *writer,
gint fd)
{
GObjectClass *klass;
GParamSpec **property_specs;
guint n_property_specs;
guint i;
write (writer->fd, man_page_header, strlen (man_page_header));
write (fd, man_page_header, strlen (man_page_header));
klass = G_OBJECT_GET_CLASS (rc);
property_specs = g_object_class_list_properties (klass, &n_property_specs);
@ -316,16 +320,16 @@ dump_gimprc_manpage (GObject *rc,
if (! (prop_spec->flags & GIMP_PARAM_SERIALIZE))
continue;
write (writer->fd, ".TP\n", strlen (".TP\n"));
write (fd, ".TP\n", strlen (".TP\n"));
if (gimp_config_serialize_property (rc, prop_spec, writer))
{
write (writer->fd, "\n", 1);
write (fd, "\n", 1);
desc = dump_describe_param (prop_spec);
dump_with_linebreaks (writer->fd, desc);
write (writer->fd, "\n", 1);
dump_with_linebreaks (fd, desc);
write (fd, "\n", 1);
g_free (desc);
}
@ -333,8 +337,8 @@ dump_gimprc_manpage (GObject *rc,
g_free (property_specs);
write (writer->fd, man_page_path, strlen (man_page_path));
write (writer->fd, man_page_footer, strlen (man_page_footer));
write (fd, man_page_path, strlen (man_page_path));
write (fd, man_page_footer, strlen (man_page_footer));
}

View File

@ -171,7 +171,7 @@ gimp_config_iface_reset (GObject *object)
}
/**
* gimp_config_serialize:
* gimp_config_serialize_to_file:
* @object: a #GObject that implements the #GimpConfigInterface.
* @filename: the name of the file to write the configuration to.
* @header: optional file header (must be ASCII only)
@ -187,12 +187,12 @@ gimp_config_iface_reset (GObject *object)
* Return value: %TRUE if serialization succeeded, %FALSE otherwise.
**/
gboolean
gimp_config_serialize (GObject *object,
const gchar *filename,
const gchar *header,
const gchar *footer,
gpointer data,
GError **error)
gimp_config_serialize_to_file (GObject *object,
const gchar *filename,
const gchar *header,
const gchar *footer,
gpointer data,
GError **error)
{
GimpConfigInterface *gimp_config_iface;
GimpConfigWriter *writer;
@ -202,11 +202,9 @@ gimp_config_serialize (GObject *object,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
writer = gimp_config_writer_new (filename, TRUE, header, error);
writer = gimp_config_writer_new_file (filename, TRUE, header, error);
if (!writer)
return FALSE;
@ -215,6 +213,38 @@ gimp_config_serialize (GObject *object,
return gimp_config_writer_finish (writer, footer, error);
}
/**
* gimp_config_serialize_to_string:
* @object: a #GObject that implements the #GimpConfigInterface.
* @data: user data passed to the serialize implementation.
*
* Serializes the object properties of @object to a string.
*
* Return value: a newly allocated %NUL-terminated string.
**/
gchar *
gimp_config_serialize_to_string (GObject *object,
gpointer data)
{
GimpConfigInterface *gimp_config_iface;
GimpConfigWriter *writer;
GString *str;
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
str = g_string_new (NULL);
writer = gimp_config_writer_new_string (str);
gimp_config_iface->serialize (object, writer, data);
gimp_config_writer_finish (writer, NULL, NULL);
return g_string_free (str, FALSE);
}
/**
* gimp_config_deserialize:
* @object: a #GObject that implements the #GimpConfigInterface.
@ -230,10 +260,10 @@ gimp_config_serialize (GObject *object,
* Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
**/
gboolean
gimp_config_deserialize (GObject *object,
const gchar *filename,
gpointer data,
GError **error)
gimp_config_deserialize_file (GObject *object,
const gchar *filename,
gpointer data,
GError **error)
{
GimpConfigInterface *gimp_config_iface;
GScanner *scanner;
@ -244,11 +274,9 @@ gimp_config_deserialize (GObject *object,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
scanner = gimp_scanner_new (filename, error);
scanner = gimp_scanner_new_file (filename, error);
if (! scanner)
return FALSE;
@ -262,6 +290,49 @@ gimp_config_deserialize (GObject *object,
return success;
}
/**
* gimp_config_deserialize_string:
* @object: a #GObject that implements the #GimpConfigInterface.
* @text: string to deserialize (in UTF-8 encoding)
* @text_len: length of @text in bytes or -1
* @error:
*
* Configures @object from @text. Basically this function creates a
* properly configured #GScanner for you and calls the deserialize
* function of the @object's #GimpConfigInterface.
*
* Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
**/
gboolean
gimp_config_deserialize_string (GObject *object,
const gchar *text,
gint text_len,
gpointer data,
GError **error)
{
GimpConfigInterface *gimp_config_iface;
GScanner *scanner;
gboolean success;
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (text != NULL || text_len == 0, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
scanner = gimp_scanner_new_string (text, text_len, error);
success = gimp_config_iface->deserialize (object, scanner, 0, data);
gimp_scanner_destroy (scanner);
if (! success)
g_assert (error == NULL || *error != NULL);
return success;
}
gboolean
gimp_config_deserialize_return (GScanner *scanner,
GTokenType expected_token,

View File

@ -71,17 +71,23 @@ typedef void (* GimpConfigForeachFunc) (const gchar *key,
GType gimp_config_interface_get_type (void) G_GNUC_CONST;
gboolean gimp_config_serialize (GObject *object,
gboolean gimp_config_serialize_to_file (GObject *object,
const gchar *filename,
const gchar *header,
const gchar *footer,
gpointer data,
GError **error);
gboolean gimp_config_deserialize (GObject *object,
gchar * gimp_config_serialize_to_string (GObject *object,
gpointer data);
gboolean gimp_config_deserialize_file (GObject *object,
const gchar *filename,
gpointer data,
GError **error);
gboolean gimp_config_deserialize_string (GObject *object,
const gchar *text,
gint text_len,
gpointer data,
GError **error);
gboolean gimp_config_deserialize_return (GScanner *scanner,
GTokenType expected_token,
gint nest_level);

View File

@ -47,15 +47,27 @@
#include "gimp-intl.h"
struct _GimpConfigWriter
{
gint fd;
gchar *filename;
gchar *tmpname;
GError *error;
GString *buffer;
gint depth;
gint marker;
};
static gboolean gimp_config_writer_close_file (GimpConfigWriter *writer,
GError **error);
GimpConfigWriter *
gimp_config_writer_new (const gchar *filename,
gboolean safe,
const gchar *header,
GError **error)
gimp_config_writer_new_file (const gchar *filename,
gboolean safe,
const gchar *header,
GError **error)
{
GimpConfigWriter *writer;
gchar *tmpname = NULL;
@ -111,7 +123,7 @@ gimp_config_writer_new (const gchar *filename,
}
GimpConfigWriter *
gimp_config_writer_new_from_fd (gint fd)
gimp_config_writer_new_fd (gint fd)
{
GimpConfigWriter *writer;
@ -125,6 +137,20 @@ gimp_config_writer_new_from_fd (gint fd)
return writer;
}
GimpConfigWriter *
gimp_config_writer_new_string (GString *string)
{
GimpConfigWriter *writer;
g_return_val_if_fail (string != NULL, NULL);
writer = g_new0 (GimpConfigWriter, 1);
writer->buffer = string;
return writer;
}
void
gimp_config_writer_open (GimpConfigWriter *writer,
const gchar *name)
@ -237,13 +263,16 @@ gimp_config_writer_close (GimpConfigWriter *writer)
if (--writer->depth == 0)
{
g_string_append_c (writer->buffer, '\n');
if (write (writer->fd, writer->buffer->str, writer->buffer->len) < 0)
g_set_error (&writer->error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
g_strerror (errno));
g_string_truncate (writer->buffer, 0);
if (writer->fd)
{
if (write (writer->fd, writer->buffer->str, writer->buffer->len) < 0)
g_set_error (&writer->error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
g_strerror (errno));
g_string_truncate (writer->buffer, 0);
}
}
}
@ -273,12 +302,19 @@ gimp_config_writer_finish (GimpConfigWriter *writer,
gimp_config_writer_comment (writer, footer);
}
success = gimp_config_writer_close_file (writer, error);
if (writer->fd)
{
success = gimp_config_writer_close_file (writer, error);
g_free (writer->filename);
g_free (writer->tmpname);
g_free (writer->filename);
g_free (writer->tmpname);
g_string_free (writer->buffer, TRUE);
g_string_free (writer->buffer, TRUE);
}
else
{
success = TRUE;
}
g_free (writer);
@ -335,6 +371,8 @@ static gboolean
gimp_config_writer_close_file (GimpConfigWriter *writer,
GError **error)
{
g_return_val_if_fail (writer->fd != 0, FALSE);
if (! writer->filename)
return TRUE;

View File

@ -23,24 +23,12 @@
#define __GIMP_CONFIG_WRITER_H__
struct _GimpConfigWriter
{
/*< private >*/
gint fd;
gchar *filename;
gchar *tmpname;
GError *error;
GString *buffer;
gint depth;
gint marker;
};
GimpConfigWriter * gimp_config_writer_new (const gchar *filename,
GimpConfigWriter * gimp_config_writer_new_file (const gchar *filename,
gboolean safe,
const gchar *header,
GError **error);
GimpConfigWriter * gimp_config_writer_new_from_fd (gint fd);
GimpConfigWriter * gimp_config_writer_new_fd (gint fd);
GimpConfigWriter * gimp_config_writer_new_string (GString *string);
void gimp_config_writer_open (GimpConfigWriter *writer,
const gchar *name);

View File

@ -287,12 +287,13 @@ gimp_rc_serialize (GObject *object,
{
if (data && GIMP_IS_RC (data))
{
if (!gimp_config_serialize_properties_diff (object, G_OBJECT (data), writer))
if (! gimp_config_serialize_properties_diff (object,
G_OBJECT (data), writer))
return FALSE;
}
else
{
if (!gimp_config_serialize_properties (object, writer))
if (! gimp_config_serialize_properties (object, writer))
return FALSE;
}
@ -340,8 +341,8 @@ gimp_rc_load (GimpRc *rc)
if (rc->verbose)
g_print (_("Parsing '%s'\n"), rc->system_gimprc);
if (! gimp_config_deserialize (G_OBJECT (rc),
rc->system_gimprc, NULL, &error))
if (! gimp_config_deserialize_file (G_OBJECT (rc),
rc->system_gimprc, NULL, &error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
@ -352,8 +353,8 @@ gimp_rc_load (GimpRc *rc)
if (rc->verbose)
g_print (_("Parsing '%s'\n"), rc->user_gimprc);
if (! gimp_config_deserialize (G_OBJECT (rc),
rc->user_gimprc, NULL, &error))
if (! gimp_config_deserialize_file (G_OBJECT (rc),
rc->user_gimprc, NULL, &error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
@ -567,16 +568,18 @@ gimp_rc_save (GimpRc *rc)
global = g_object_new (GIMP_TYPE_RC, NULL);
gimp_config_deserialize (G_OBJECT (global), rc->system_gimprc, NULL, NULL);
gimp_config_deserialize_file (G_OBJECT (global),
rc->system_gimprc, NULL, NULL);
header = g_strconcat (top, rc->system_gimprc, bottom, NULL);
if (rc->verbose)
g_print (_("Saving '%s'\n"), rc->user_gimprc);
if (! gimp_config_serialize (G_OBJECT (rc),
rc->user_gimprc, header, footer, global,
&error))
if (! gimp_config_serialize_to_file (G_OBJECT (rc),
rc->user_gimprc,
header, footer, global,
&error))
{
g_message (error->message);
g_error_free (error);

View File

@ -49,21 +49,23 @@
/* local function prototypes */
static void gimp_scanner_message (GScanner *scanner,
gchar *message,
gboolean is_error);
static GScanner * gimp_scanner_new (GError **error);
static void gimp_scanner_message (GScanner *scanner,
gchar *message,
gboolean is_error);
/* public functions */
GScanner *
gimp_scanner_new (const gchar *filename,
GError **error)
gimp_scanner_new_file (const gchar *filename,
GError **error)
{
gint fd;
GScanner *scanner;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
fd = open (filename, O_RDONLY);
@ -78,13 +80,43 @@ gimp_scanner_new (const gchar *filename,
return NULL;
}
scanner = g_scanner_new (NULL);
scanner = gimp_scanner_new (error);
g_scanner_input_file (scanner, fd);
scanner->input_name = g_strdup (filename);
return scanner;
}
GScanner *
gimp_scanner_new_string (const gchar *text,
gint text_len,
GError **error)
{
GScanner *scanner;
g_return_val_if_fail (text != NULL || text_len == 0, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (text_len < 0)
text_len = strlen (text);
scanner = gimp_scanner_new (error);
g_scanner_input_text (scanner, text, text_len);
return scanner;
}
static GScanner *
gimp_scanner_new (GError **error)
{
GScanner *scanner;
scanner = g_scanner_new (NULL);
scanner->user_data = error;
scanner->msg_handler = gimp_scanner_message;
scanner->input_name = g_strdup (filename);
scanner->config->cset_identifier_first = ( G_CSET_a_2_z G_CSET_A_2_Z );
scanner->config->cset_identifier_nth = ( G_CSET_a_2_z G_CSET_A_2_Z
@ -349,8 +381,13 @@ gimp_scanner_message (GScanner *scanner,
/* we don't expect warnings */
g_return_if_fail (is_error);
g_set_error (error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
_("Error while parsing '%s' in line %d:\n%s"),
scanner->input_name, scanner->line, message);
if (scanner->input_name)
g_set_error (error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
_("Error while parsing '%s' in line %d:\n%s"),
scanner->input_name, scanner->line, message);
else
g_set_error (error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
"Error parsing internal buffer: %s", message);
}

View File

@ -24,7 +24,10 @@
#define __GIMP_SCANNER_H__
GScanner * gimp_scanner_new (const gchar *filename,
GScanner * gimp_scanner_new_file (const gchar *filename,
GError **error);
GScanner * gimp_scanner_new_string (const gchar *text,
gint text_len,
GError **error);
void gimp_scanner_destroy (GScanner *scanner);

View File

@ -33,6 +33,7 @@
#include "gimpconfig.h"
#include "gimpconfig-serialize.h"
#include "gimpconfig-utils.h"
#include "gimprc.h"
@ -47,8 +48,8 @@ int
main (int argc,
char *argv[])
{
GimpRc *gimprc;
GimpRc *gimprc2;
GObject *gimprc;
GObject *gimprc2;
const gchar *filename = "foorc";
gchar *header;
gchar *result;
@ -76,17 +77,16 @@ main (int argc,
g_print (" done.\n\n");
g_print (" Adding the unknown token (foobar \"hadjaha\") ...");
gimp_config_add_unknown_token (G_OBJECT (gimprc), "foobar", "hadjaha");
gimp_config_add_unknown_token (gimprc, "foobar", "hadjaha");
g_print (" done.\n\n");
g_print (" Serializing %s to '%s' ...",
g_type_name (G_TYPE_FROM_INSTANCE (gimprc)), filename);
if (! gimp_config_serialize (G_OBJECT (gimprc),
filename,
"foorc",
"end of foorc",
NULL, &error))
if (! gimp_config_serialize_to_file (gimprc,
filename,
"foorc", "end of foorc",
NULL, &error))
{
g_print ("%s\n", error->message);
return EXIT_FAILURE;
@ -98,21 +98,20 @@ main (int argc,
NULL);
g_print (" Deserializing from '%s' ...\n\n", filename);
if (! gimp_config_deserialize (G_OBJECT (gimprc), filename, NULL, &error))
if (! gimp_config_deserialize_file (gimprc, filename, NULL, &error))
{
g_print ("%s\n", error->message);
return EXIT_FAILURE;
}
header = "\n Unknown string tokens:\n";
gimp_config_foreach_unknown_token (G_OBJECT (gimprc),
output_unknown_token, &header);
gimp_config_foreach_unknown_token (gimprc, output_unknown_token, &header);
g_print ("\n done.\n");
g_print ("\n Changing a property ...");
g_object_set (gimprc, "use-help", FALSE, NULL);
g_print ("\n Testing gimp_config_duplicate() ...");
gimprc2 = GIMP_RC (gimp_config_duplicate (G_OBJECT (gimprc)));
gimprc2 = gimp_config_duplicate (gimprc);
g_print (" done.\n");
g_signal_connect (gimprc2, "notify",
@ -124,7 +123,7 @@ main (int argc,
g_print ("\n Querying for \"default-comment\" ... ");
result = gimp_rc_query (gimprc2, "default-comment");
result = gimp_rc_query (GIMP_RC (gimprc2), "default-comment");
if (result)
{
g_print ("OK, found \"%s\".\n", result);
@ -138,7 +137,7 @@ main (int argc,
g_print (" Querying for \"foobar\" ... ");
result = gimp_rc_query (gimprc2, "foobar");
result = gimp_rc_query (GIMP_RC (gimprc2), "foobar");
if (result && strcmp (result, "hadjaha") == 0)
{
g_print ("OK, found \"%s\".\n", result);
@ -154,11 +153,11 @@ main (int argc,
g_object_unref (gimprc2);
g_print ("\n Deserializing from gimpconfig.c (should fail) ...");
if (! gimp_config_deserialize (G_OBJECT (gimprc),
"gimpconfig.c", NULL, &error))
if (! gimp_config_deserialize_file (gimprc, "gimpconfig.c", NULL, &error))
{
g_print (" OK, failed. The error was:\n %s\n", error->message);
g_error_free (error);
error = NULL;
}
else
{
@ -166,6 +165,40 @@ main (int argc,
return EXIT_FAILURE;
}
g_print ("\n Serializing to a string and back ... ");
result = gimp_config_serialize_to_string (gimprc, NULL);
gimprc2 = g_object_new (GIMP_TYPE_RC, NULL);
if (! gimp_config_deserialize_string (gimprc2, result, -1, NULL, &error))
{
g_print ("failed!\nThe error was:\n %s\n", error->message);
g_error_free (error);
return EXIT_FAILURE;
}
else
{
GList *diff = gimp_config_diff (gimprc, gimprc2, 0);
if (diff)
{
GList *list;
g_print ("succeeded but properties differ:\n");
for (list = diff; list; list = list->next)
{
GParamSpec *pspec = list->data;
g_print (" %s\n", pspec->name);
}
return EXIT_FAILURE;
}
g_print ("OK (%d bytes)\n", result ? strlen (result) : 0);
}
g_free (result);
g_object_unref (gimprc2);
g_object_unref (gimprc);
g_print ("\nFinished test of GimpConfig.\n\n");

View File

@ -45,10 +45,10 @@ gimp_documents_load (Gimp *gimp)
filename = gimp_personal_rc_file ("documents");
if (!gimp_config_deserialize (G_OBJECT (gimp->documents),
filename,
GINT_TO_POINTER (gimp->config->thumbnail_size),
&error))
if (! gimp_config_deserialize_file (G_OBJECT (gimp->documents),
filename,
GINT_TO_POINTER (gimp->config->thumbnail_size),
&error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
@ -76,8 +76,10 @@ gimp_documents_save (Gimp *gimp)
filename = gimp_personal_rc_file ("documents");
if (! gimp_config_serialize (G_OBJECT (gimp->documents),
filename, header, footer, NULL, &error))
if (! gimp_config_serialize_to_file (G_OBJECT (gimp->documents),
filename,
header, footer, NULL,
&error))
{
g_message (error->message);
g_error_free (error);

View File

@ -100,8 +100,8 @@ gimp_parasiterc_load (Gimp *gimp)
filename = gimp_personal_rc_file ("parasiterc");
if (! gimp_config_deserialize (G_OBJECT (gimp->parasites),
filename, NULL, &error))
if (! gimp_config_deserialize_file (G_OBJECT (gimp->parasites),
filename, NULL, &error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
@ -129,8 +129,10 @@ gimp_parasiterc_save (Gimp *gimp)
filename = gimp_personal_rc_file ("parasiterc");
if (! gimp_config_serialize (G_OBJECT (gimp->parasites),
filename, header, footer, NULL, &error))
if (! gimp_config_serialize_to_file (G_OBJECT (gimp->parasites),
filename,
header, footer, NULL,
&error))
{
g_message (error->message);
g_error_free (error);

View File

@ -45,10 +45,10 @@ gimp_templates_load (Gimp *gimp)
filename = gimp_personal_rc_file ("templaterc");
if (!gimp_config_deserialize (G_OBJECT (gimp->templates),
filename,
NULL,
&error))
if (!gimp_config_deserialize_file (G_OBJECT (gimp->templates),
filename,
NULL,
&error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
@ -78,8 +78,10 @@ gimp_templates_save (Gimp *gimp)
filename = gimp_personal_rc_file ("templaterc");
if (! gimp_config_serialize (G_OBJECT (gimp->templates),
filename, header, footer, NULL, &error))
if (! gimp_config_serialize_to_file (G_OBJECT (gimp->templates),
filename,
header, footer, NULL,
&error))
{
g_message (error->message);
g_error_free (error);

View File

@ -97,7 +97,7 @@ gimp_unitrc_load (Gimp *gimp)
g_return_if_fail (GIMP_IS_GIMP (gimp));
filename = gimp_personal_rc_file ("unitrc");
scanner = gimp_scanner_new (filename, &error);
scanner = gimp_scanner_new_file (filename, &error);
g_free (filename);
if (! scanner)
@ -174,16 +174,17 @@ gimp_unitrc_save (Gimp *gimp)
filename = gimp_personal_rc_file ("unitrc");
writer = gimp_config_writer_new (filename,
TRUE,
"GIMP units\n\n"
"This file contains the user unit database. "
"You can edit this list with the unit "
"editor. You are not supposed to edit it "
"manually, but of course you can do.\n"
"This file will be entirely rewritten every "
"time you quit the gimp.",
NULL);
writer =
gimp_config_writer_new_file (filename,
TRUE,
"GIMP units\n\n"
"This file contains the user unit database. "
"You can edit this list with the unit "
"editor. You are not supposed to edit it "
"manually, but of course you can do.\n"
"This file will be entirely rewritten every "
"time you quit the gimp.",
NULL);
g_free (filename);

View File

@ -1259,7 +1259,7 @@ gimp_layer_boundary (GimpLayer *layer,
new_segs[0].y2 = item->offset_y + item->height;
new_segs[0].open = 1;
new_segs[1].x1 = item->offset_x;
new_segs[1].x1 = item->offset_x;
new_segs[1].y1 = item->offset_y;
new_segs[1].x2 = item->offset_x + item->width;
new_segs[1].y2 = item->offset_y;

View File

@ -215,12 +215,12 @@ gimp_tool_options_serialize (GimpToolOptions *tool_options,
filename = gimp_tool_options_build_filename (tool_options, extension);
retval = gimp_config_serialize (G_OBJECT (tool_options),
filename,
"GIMP tool options",
"end of tool options",
NULL,
error);
retval = gimp_config_serialize_to_file (G_OBJECT (tool_options),
filename,
"GIMP tool options",
"end of tool options",
NULL,
error);
g_free (filename);
@ -240,10 +240,10 @@ gimp_tool_options_deserialize (GimpToolOptions *tool_options,
filename = gimp_tool_options_build_filename (tool_options, extension);
retval = gimp_config_deserialize (G_OBJECT (tool_options),
filename,
NULL,
error);
retval = gimp_config_deserialize_file (G_OBJECT (tool_options),
filename,
NULL,
error);
g_free (filename);

View File

@ -97,7 +97,7 @@ gimp_unitrc_load (Gimp *gimp)
g_return_if_fail (GIMP_IS_GIMP (gimp));
filename = gimp_personal_rc_file ("unitrc");
scanner = gimp_scanner_new (filename, &error);
scanner = gimp_scanner_new_file (filename, &error);
g_free (filename);
if (! scanner)
@ -174,16 +174,17 @@ gimp_unitrc_save (Gimp *gimp)
filename = gimp_personal_rc_file ("unitrc");
writer = gimp_config_writer_new (filename,
TRUE,
"GIMP units\n\n"
"This file contains the user unit database. "
"You can edit this list with the unit "
"editor. You are not supposed to edit it "
"manually, but of course you can do.\n"
"This file will be entirely rewritten every "
"time you quit the gimp.",
NULL);
writer =
gimp_config_writer_new_file (filename,
TRUE,
"GIMP units\n\n"
"This file contains the user unit database. "
"You can edit this list with the unit "
"editor. You are not supposed to edit it "
"manually, but of course you can do.\n"
"This file will be entirely rewritten every "
"time you quit the gimp.",
NULL);
g_free (filename);

View File

@ -80,7 +80,7 @@ session_init (Gimp *gimp)
g_return_if_fail (GIMP_IS_GIMP (gimp));
filename = gimp_personal_rc_file ("sessionrc");
scanner = gimp_scanner_new (filename, &error);
scanner = gimp_scanner_new_file (filename, &error);
g_free (filename);
if (! scanner)
@ -205,18 +205,19 @@ session_save (Gimp *gimp)
filename = gimp_personal_rc_file ("sessionrc");
writer = gimp_config_writer_new (filename,
TRUE,
"GIMP sessionrc\n\n"
"This file takes session-specific info "
"(that is info, you want to keep between "
"two gimp-sessions). You are not supposed "
"to edit it manually, but of course you "
"can do.\n"
"This file will be entirely rewritten "
"every time you quit the gimp. If this "
"file isn't found, defaults are used.",
NULL);
writer =
gimp_config_writer_new_file (filename,
TRUE,
"GIMP sessionrc\n\n"
"This file takes session-specific info "
"(that is info, you want to keep between "
"two gimp-sessions). You are not supposed "
"to edit it manually, but of course you "
"can do.\n"
"This file will be entirely rewritten "
"every time you quit the gimp. If this "
"file isn't found, defaults are used.",
NULL);
if (!writer)
return;

View File

@ -79,7 +79,7 @@ plug_in_rc_parse (Gimp *gimp,
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
scanner = gimp_scanner_new (filename, &error);
scanner = gimp_scanner_new_file (filename, &error);
if (! scanner)
return TRUE;
@ -391,13 +391,13 @@ plug_in_rc_write (GSList *plug_in_defs,
GSList *list2;
gint i;
writer = gimp_config_writer_new (filename,
FALSE,
"GIMP plug-ins\n\n"
"This file can safely be removed and will "
"be automatically regenerated by querying "
"the installed plugins.",
error);
writer = gimp_config_writer_new_file (filename,
FALSE,
"GIMP plug-ins\n\n"
"This file can safely be removed and "
"will be automatically regenerated by "
"querying the installed plugins.",
error);
if (!writer)
return FALSE;

View File

@ -215,12 +215,12 @@ gimp_tool_options_serialize (GimpToolOptions *tool_options,
filename = gimp_tool_options_build_filename (tool_options, extension);
retval = gimp_config_serialize (G_OBJECT (tool_options),
filename,
"GIMP tool options",
"end of tool options",
NULL,
error);
retval = gimp_config_serialize_to_file (G_OBJECT (tool_options),
filename,
"GIMP tool options",
"end of tool options",
NULL,
error);
g_free (filename);
@ -240,10 +240,10 @@ gimp_tool_options_deserialize (GimpToolOptions *tool_options,
filename = gimp_tool_options_build_filename (tool_options, extension);
retval = gimp_config_deserialize (G_OBJECT (tool_options),
filename,
NULL,
error);
retval = gimp_config_deserialize_file (G_OBJECT (tool_options),
filename,
NULL,
error);
g_free (filename);

View File

@ -128,10 +128,10 @@ gimp_devices_restore (Gimp *gimp)
filename = gimp_personal_rc_file ("devicerc");
if (! gimp_config_deserialize (G_OBJECT (manager->device_info_list),
filename,
gimp,
&error))
if (! gimp_config_deserialize_file (G_OBJECT (manager->device_info_list),
filename,
gimp,
&error))
{
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
g_message (error->message);
@ -170,12 +170,12 @@ gimp_devices_save (Gimp *gimp)
filename = gimp_personal_rc_file ("devicerc");
if (! gimp_config_serialize (G_OBJECT (manager->device_info_list),
filename,
"GIMP devicerc",
"end of devicerc",
NULL,
&error))
if (! gimp_config_serialize_to_file (G_OBJECT (manager->device_info_list),
filename,
"GIMP devicerc",
"end of devicerc",
NULL,
&error))
{
g_message (error->message);
g_error_free (error);

View File

@ -184,7 +184,7 @@ gimp_parasite_name (const GimpParasite *parasite)
return NULL;
}
gpointer
gconstpointer
gimp_parasite_data (const GimpParasite *parasite)
{
if (parasite)

View File

@ -50,27 +50,27 @@ struct _GimpParasite
};
GimpParasite * gimp_parasite_new (const gchar *name,
guint32 flags,
guint32 size,
const gpointer data);
void gimp_parasite_free (GimpParasite *parasite);
GimpParasite * gimp_parasite_new (const gchar *name,
guint32 flags,
guint32 size,
const gpointer data);
void gimp_parasite_free (GimpParasite *parasite);
GimpParasite * gimp_parasite_copy (const GimpParasite *parasite);
GimpParasite * gimp_parasite_copy (const GimpParasite *parasite);
gboolean gimp_parasite_compare (const GimpParasite *a,
const GimpParasite *b);
gboolean gimp_parasite_compare (const GimpParasite *a,
const GimpParasite *b);
gboolean gimp_parasite_is_type (const GimpParasite *parasite,
const gchar *name);
gboolean gimp_parasite_is_persistent (const GimpParasite *parasite);
gboolean gimp_parasite_is_undoable (const GimpParasite *parasite);
gboolean gimp_parasite_has_flag (const GimpParasite *parasite,
gulong flag);
gulong gimp_parasite_flags (const GimpParasite *parasite);
const gchar * gimp_parasite_name (const GimpParasite *parasite);
gpointer gimp_parasite_data (const GimpParasite *parasite);
glong gimp_parasite_data_size (const GimpParasite *parasite);
gboolean gimp_parasite_is_type (const GimpParasite *parasite,
const gchar *name);
gboolean gimp_parasite_is_persistent (const GimpParasite *parasite);
gboolean gimp_parasite_is_undoable (const GimpParasite *parasite);
gboolean gimp_parasite_has_flag (const GimpParasite *parasite,
gulong flag);
gulong gimp_parasite_flags (const GimpParasite *parasite);
const gchar * gimp_parasite_name (const GimpParasite *parasite);
gconstpointer gimp_parasite_data (const GimpParasite *parasite);
glong gimp_parasite_data_size (const GimpParasite *parasite);
G_END_DECLS

View File

@ -171,7 +171,7 @@ gimp_config_iface_reset (GObject *object)
}
/**
* gimp_config_serialize:
* gimp_config_serialize_to_file:
* @object: a #GObject that implements the #GimpConfigInterface.
* @filename: the name of the file to write the configuration to.
* @header: optional file header (must be ASCII only)
@ -187,12 +187,12 @@ gimp_config_iface_reset (GObject *object)
* Return value: %TRUE if serialization succeeded, %FALSE otherwise.
**/
gboolean
gimp_config_serialize (GObject *object,
const gchar *filename,
const gchar *header,
const gchar *footer,
gpointer data,
GError **error)
gimp_config_serialize_to_file (GObject *object,
const gchar *filename,
const gchar *header,
const gchar *footer,
gpointer data,
GError **error)
{
GimpConfigInterface *gimp_config_iface;
GimpConfigWriter *writer;
@ -202,11 +202,9 @@ gimp_config_serialize (GObject *object,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
writer = gimp_config_writer_new (filename, TRUE, header, error);
writer = gimp_config_writer_new_file (filename, TRUE, header, error);
if (!writer)
return FALSE;
@ -215,6 +213,38 @@ gimp_config_serialize (GObject *object,
return gimp_config_writer_finish (writer, footer, error);
}
/**
* gimp_config_serialize_to_string:
* @object: a #GObject that implements the #GimpConfigInterface.
* @data: user data passed to the serialize implementation.
*
* Serializes the object properties of @object to a string.
*
* Return value: a newly allocated %NUL-terminated string.
**/
gchar *
gimp_config_serialize_to_string (GObject *object,
gpointer data)
{
GimpConfigInterface *gimp_config_iface;
GimpConfigWriter *writer;
GString *str;
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
str = g_string_new (NULL);
writer = gimp_config_writer_new_string (str);
gimp_config_iface->serialize (object, writer, data);
gimp_config_writer_finish (writer, NULL, NULL);
return g_string_free (str, FALSE);
}
/**
* gimp_config_deserialize:
* @object: a #GObject that implements the #GimpConfigInterface.
@ -230,10 +260,10 @@ gimp_config_serialize (GObject *object,
* Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
**/
gboolean
gimp_config_deserialize (GObject *object,
const gchar *filename,
gpointer data,
GError **error)
gimp_config_deserialize_file (GObject *object,
const gchar *filename,
gpointer data,
GError **error)
{
GimpConfigInterface *gimp_config_iface;
GScanner *scanner;
@ -244,11 +274,9 @@ gimp_config_deserialize (GObject *object,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
scanner = gimp_scanner_new (filename, error);
scanner = gimp_scanner_new_file (filename, error);
if (! scanner)
return FALSE;
@ -262,6 +290,49 @@ gimp_config_deserialize (GObject *object,
return success;
}
/**
* gimp_config_deserialize_string:
* @object: a #GObject that implements the #GimpConfigInterface.
* @text: string to deserialize (in UTF-8 encoding)
* @text_len: length of @text in bytes or -1
* @error:
*
* Configures @object from @text. Basically this function creates a
* properly configured #GScanner for you and calls the deserialize
* function of the @object's #GimpConfigInterface.
*
* Return value: %TRUE if deserialization succeeded, %FALSE otherwise.
**/
gboolean
gimp_config_deserialize_string (GObject *object,
const gchar *text,
gint text_len,
gpointer data,
GError **error)
{
GimpConfigInterface *gimp_config_iface;
GScanner *scanner;
gboolean success;
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (text != NULL || text_len == 0, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
gimp_config_iface = GIMP_GET_CONFIG_INTERFACE (object);
g_return_val_if_fail (gimp_config_iface != NULL, FALSE);
scanner = gimp_scanner_new_string (text, text_len, error);
success = gimp_config_iface->deserialize (object, scanner, 0, data);
gimp_scanner_destroy (scanner);
if (! success)
g_assert (error == NULL || *error != NULL);
return success;
}
gboolean
gimp_config_deserialize_return (GScanner *scanner,
GTokenType expected_token,

View File

@ -71,17 +71,23 @@ typedef void (* GimpConfigForeachFunc) (const gchar *key,
GType gimp_config_interface_get_type (void) G_GNUC_CONST;
gboolean gimp_config_serialize (GObject *object,
gboolean gimp_config_serialize_to_file (GObject *object,
const gchar *filename,
const gchar *header,
const gchar *footer,
gpointer data,
GError **error);
gboolean gimp_config_deserialize (GObject *object,
gchar * gimp_config_serialize_to_string (GObject *object,
gpointer data);
gboolean gimp_config_deserialize_file (GObject *object,
const gchar *filename,
gpointer data,
GError **error);
gboolean gimp_config_deserialize_string (GObject *object,
const gchar *text,
gint text_len,
gpointer data,
GError **error);
gboolean gimp_config_deserialize_return (GScanner *scanner,
GTokenType expected_token,
gint nest_level);

View File

@ -47,15 +47,27 @@
#include "gimp-intl.h"
struct _GimpConfigWriter
{
gint fd;
gchar *filename;
gchar *tmpname;
GError *error;
GString *buffer;
gint depth;
gint marker;
};
static gboolean gimp_config_writer_close_file (GimpConfigWriter *writer,
GError **error);
GimpConfigWriter *
gimp_config_writer_new (const gchar *filename,
gboolean safe,
const gchar *header,
GError **error)
gimp_config_writer_new_file (const gchar *filename,
gboolean safe,
const gchar *header,
GError **error)
{
GimpConfigWriter *writer;
gchar *tmpname = NULL;
@ -111,7 +123,7 @@ gimp_config_writer_new (const gchar *filename,
}
GimpConfigWriter *
gimp_config_writer_new_from_fd (gint fd)
gimp_config_writer_new_fd (gint fd)
{
GimpConfigWriter *writer;
@ -125,6 +137,20 @@ gimp_config_writer_new_from_fd (gint fd)
return writer;
}
GimpConfigWriter *
gimp_config_writer_new_string (GString *string)
{
GimpConfigWriter *writer;
g_return_val_if_fail (string != NULL, NULL);
writer = g_new0 (GimpConfigWriter, 1);
writer->buffer = string;
return writer;
}
void
gimp_config_writer_open (GimpConfigWriter *writer,
const gchar *name)
@ -237,13 +263,16 @@ gimp_config_writer_close (GimpConfigWriter *writer)
if (--writer->depth == 0)
{
g_string_append_c (writer->buffer, '\n');
if (write (writer->fd, writer->buffer->str, writer->buffer->len) < 0)
g_set_error (&writer->error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
g_strerror (errno));
g_string_truncate (writer->buffer, 0);
if (writer->fd)
{
if (write (writer->fd, writer->buffer->str, writer->buffer->len) < 0)
g_set_error (&writer->error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
g_strerror (errno));
g_string_truncate (writer->buffer, 0);
}
}
}
@ -273,12 +302,19 @@ gimp_config_writer_finish (GimpConfigWriter *writer,
gimp_config_writer_comment (writer, footer);
}
success = gimp_config_writer_close_file (writer, error);
if (writer->fd)
{
success = gimp_config_writer_close_file (writer, error);
g_free (writer->filename);
g_free (writer->tmpname);
g_free (writer->filename);
g_free (writer->tmpname);
g_string_free (writer->buffer, TRUE);
g_string_free (writer->buffer, TRUE);
}
else
{
success = TRUE;
}
g_free (writer);
@ -335,6 +371,8 @@ static gboolean
gimp_config_writer_close_file (GimpConfigWriter *writer,
GError **error)
{
g_return_val_if_fail (writer->fd != 0, FALSE);
if (! writer->filename)
return TRUE;

View File

@ -23,24 +23,12 @@
#define __GIMP_CONFIG_WRITER_H__
struct _GimpConfigWriter
{
/*< private >*/
gint fd;
gchar *filename;
gchar *tmpname;
GError *error;
GString *buffer;
gint depth;
gint marker;
};
GimpConfigWriter * gimp_config_writer_new (const gchar *filename,
GimpConfigWriter * gimp_config_writer_new_file (const gchar *filename,
gboolean safe,
const gchar *header,
GError **error);
GimpConfigWriter * gimp_config_writer_new_from_fd (gint fd);
GimpConfigWriter * gimp_config_writer_new_fd (gint fd);
GimpConfigWriter * gimp_config_writer_new_string (GString *string);
void gimp_config_writer_open (GimpConfigWriter *writer,
const gchar *name);

View File

@ -49,21 +49,23 @@
/* local function prototypes */
static void gimp_scanner_message (GScanner *scanner,
gchar *message,
gboolean is_error);
static GScanner * gimp_scanner_new (GError **error);
static void gimp_scanner_message (GScanner *scanner,
gchar *message,
gboolean is_error);
/* public functions */
GScanner *
gimp_scanner_new (const gchar *filename,
GError **error)
gimp_scanner_new_file (const gchar *filename,
GError **error)
{
gint fd;
GScanner *scanner;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
fd = open (filename, O_RDONLY);
@ -78,13 +80,43 @@ gimp_scanner_new (const gchar *filename,
return NULL;
}
scanner = g_scanner_new (NULL);
scanner = gimp_scanner_new (error);
g_scanner_input_file (scanner, fd);
scanner->input_name = g_strdup (filename);
return scanner;
}
GScanner *
gimp_scanner_new_string (const gchar *text,
gint text_len,
GError **error)
{
GScanner *scanner;
g_return_val_if_fail (text != NULL || text_len == 0, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (text_len < 0)
text_len = strlen (text);
scanner = gimp_scanner_new (error);
g_scanner_input_text (scanner, text, text_len);
return scanner;
}
static GScanner *
gimp_scanner_new (GError **error)
{
GScanner *scanner;
scanner = g_scanner_new (NULL);
scanner->user_data = error;
scanner->msg_handler = gimp_scanner_message;
scanner->input_name = g_strdup (filename);
scanner->config->cset_identifier_first = ( G_CSET_a_2_z G_CSET_A_2_Z );
scanner->config->cset_identifier_nth = ( G_CSET_a_2_z G_CSET_A_2_Z
@ -349,8 +381,13 @@ gimp_scanner_message (GScanner *scanner,
/* we don't expect warnings */
g_return_if_fail (is_error);
g_set_error (error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
_("Error while parsing '%s' in line %d:\n%s"),
scanner->input_name, scanner->line, message);
if (scanner->input_name)
g_set_error (error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
_("Error while parsing '%s' in line %d:\n%s"),
scanner->input_name, scanner->line, message);
else
g_set_error (error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
"Error parsing internal buffer: %s", message);
}

View File

@ -24,7 +24,10 @@
#define __GIMP_SCANNER_H__
GScanner * gimp_scanner_new (const gchar *filename,
GScanner * gimp_scanner_new_file (const gchar *filename,
GError **error);
GScanner * gimp_scanner_new_string (const gchar *text,
gint text_len,
GError **error);
void gimp_scanner_destroy (GScanner *scanner);