Commit f30586d1 authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

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.
parent dffe80c2
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:
......@@ -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));
}
......
......@@ -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,
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
}
......@@ -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);
......
......@@ -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,