2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2002 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * General functions for saving properties to an XML file.
23 * The file is structured as follows:
26 * <property name="first-name" value="Axle" >/
27 * <property name="last-name" value="Rose" >/
30 * ***********************************************************************
42 /* Element tag names */
43 #define XMLS_ELTAG_PROP_LIST "property-list"
44 #define XMLS_ELTAG_PROPERTY "property"
46 /* Attribute tag names */
47 #define XMLS_ATTAG_NAME "name"
48 #define XMLS_ATTAG_VALUE "value"
53 XmlProperty *xmlprops_create( void ) {
56 props = g_new0( XmlProperty, 1 );
58 props->encoding = NULL;
59 props->propertyTable = g_hash_table_new( g_str_hash, g_str_equal );
60 props->retVal = MGU_SUCCESS;
65 * Properties - file path.
67 void xmlprops_set_path( XmlProperty *props, const gchar *value ) {
68 g_return_if_fail( props != NULL );
69 props->path = mgu_replace_string( props->path, value );
71 void xmlprops_set_encoding( XmlProperty *props, const gchar *value ) {
72 g_return_if_fail( props != NULL );
73 props->encoding = mgu_replace_string( props->encoding, value );
77 * Free hash table visitor function.
79 static gint xmlprops_free_entry_vis( gpointer key, gpointer value, gpointer data ) {
88 * Clear all properties.
89 * Enter: props Property object.
91 void xmlprops_clear( XmlProperty *props ) {
92 g_return_if_fail( props != NULL );
93 g_hash_table_foreach_remove(
94 props->propertyTable, xmlprops_free_entry_vis, NULL );
99 * Enter: props Property object.
101 void xmlprops_free( XmlProperty *props ) {
102 g_return_if_fail( props != NULL );
104 /* Clear property table */
105 xmlprops_clear( props );
106 g_hash_table_destroy( props->propertyTable );
108 /* Free up internal objects */
109 g_free( props->path );
110 g_free( props->encoding );
113 props->encoding = NULL;
114 props->propertyTable = NULL;
120 static void xmlprops_write_elem_s( FILE *fp, gint lvl, gchar *name ) {
122 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
127 static void xmlprops_write_elem_e( FILE *fp, gint lvl, gchar *name ) {
129 for( i = 0; i < lvl; i++ ) fputs( " ", fp );
135 static void xmlprops_write_attr( FILE *fp, gchar *name, gchar *value ) {
139 xml_file_put_escape_str( fp, value );
143 static void xmlprops_write_vis( gpointer key, gpointer value, gpointer data ) {
144 FILE *fp = ( FILE * ) data;
146 xmlprops_write_elem_s( fp, 1, XMLS_ELTAG_PROPERTY );
147 xmlprops_write_attr( fp, XMLS_ATTAG_NAME, key );
148 xmlprops_write_attr( fp, XMLS_ATTAG_VALUE, value );
149 fputs( " />\n", fp );
152 static gint xmlprops_write_to( XmlProperty *props, const gchar *fileSpec ) {
156 props->retVal = MGU_OPEN_FILE;
157 pfile = prefs_write_open( fileSpec );
160 fprintf( fp, "<?xml version=\"1.0\"" );
161 if( props->encoding && *props->encoding ) {
162 fprintf( fp, " encoding=\"%s\"", props->encoding );
164 fprintf( fp, " ?>\n" );
165 xmlprops_write_elem_s( fp, 0, XMLS_ELTAG_PROP_LIST );
168 /* Output all properties */
169 g_hash_table_foreach( props->propertyTable, xmlprops_write_vis, fp );
171 xmlprops_write_elem_e( fp, 0, XMLS_ELTAG_PROP_LIST );
172 props->retVal = MGU_SUCCESS;
173 if( prefs_file_close( pfile ) < 0 ) {
174 props->retVal = MGU_ERROR_WRITE;
178 return props->retVal;
182 * Save properties to file.
183 * return: Status code.
185 gint xmlprops_save_file( XmlProperty *props ) {
186 g_return_val_if_fail( props != NULL, -1 );
188 props->retVal = MGU_NO_FILE;
189 if( props->path == NULL || *props->path == '\0' ) return props->retVal;
190 xmlprops_write_to( props, props->path );
192 if( props->retVal == MGU_SUCCESS ) {
195 return props->retVal;
198 static void xmlprops_print_vis( gpointer key, gpointer value, gpointer data ) {
199 FILE *stream = ( FILE * ) data;
201 fprintf( stream, "-\tname/value:\t%s / %s\n", (char *)key, (char *)value );
204 void xmlprops_print( XmlProperty *props, FILE *stream ) {
205 fprintf( stream, "Property File: %s\n", props->path );
206 g_hash_table_foreach( props->propertyTable, xmlprops_print_vis, stream );
207 fprintf( stream, "---\n" );
210 static void xmlprops_save_property(
211 XmlProperty *props, const gchar *name, const gchar *value )
216 if( strlen( name ) == 0 ) return;
217 if( strlen( value ) == 0 ) return;
218 if( g_hash_table_lookup( props->propertyTable, name ) ) return;
219 key = g_strdup( name );
220 val = g_strdup( value );
221 g_hash_table_insert( props->propertyTable, key, val );
224 #define ATTR_BUFSIZE 256
226 static void xmlprops_read_props( XmlProperty *props, XMLFile *file ) {
229 gchar pName[ ATTR_BUFSIZE ];
230 gchar pValue[ ATTR_BUFSIZE ];
235 if (! file->level ) break;
236 xml_parse_next_tag( file );
237 xml_get_current_tag( file );
238 if( xml_compare_tag( file, XMLS_ELTAG_PROPERTY ) ) {
239 attr = xml_get_current_tag_attr( file );
241 name = ( ( XMLAttr * ) attr->data )->name;
242 value = ( ( XMLAttr * ) attr->data )->value;
243 if( strcmp( name, XMLS_ATTAG_NAME ) == 0 ) {
244 strcpy( pName, value );
246 else if( strcmp( name, XMLS_ATTAG_VALUE ) == 0 ) {
247 strcpy( pValue, value );
249 attr = g_list_next( attr );
251 xmlprops_save_property( props, pName, pValue );
259 * Load properties from file.
260 * return: Status code.
262 gint xmlprops_load_file( XmlProperty *props ) {
263 XMLFile *file = NULL;
265 g_return_val_if_fail( props != NULL, -1 );
266 props->retVal = MGU_NO_FILE;
267 file = xml_open_file( props->path );
269 return props->retVal;
272 props->retVal = MGU_BAD_FORMAT;
273 if( xml_get_dtd( file ) == 0 ) {
274 if( xml_parse_next_tag( file ) == 0 ) {
275 if( xml_compare_tag( file, XMLS_ELTAG_PROP_LIST ) ) {
276 xmlprops_read_props( props, file );
277 props->retVal = MGU_SUCCESS;
281 xml_close_file( file );
283 return props->retVal;
288 * Enter: props Property object.
289 * name Property name.
290 * value New value to save.
292 void xmlprops_set_property(
293 XmlProperty *props, const gchar *name, const gchar *value )
298 g_return_if_fail( props != NULL );
299 if( name == NULL || strlen( name ) == 0 ) return;
300 if( value == NULL || strlen( value ) == 0 ) return;
301 val = g_hash_table_lookup( props->propertyTable, name );
303 key = g_strdup( name );
308 val = g_strdup( value );
309 g_hash_table_insert( props->propertyTable, key, val );
313 * Set property to integer value.
314 * Enter: props Property object.
315 * name Property name.
316 * value New value to save.
318 void xmlprops_set_property_i(
319 XmlProperty *props, const gchar *name, const gint value )
323 g_return_if_fail( props != NULL );
324 sprintf( buf, "%d", value );
325 xmlprops_set_property( props, name, buf );
329 * Set property to boolean value.
330 * Enter: props Property object.
331 * name Property name.
332 * value New value to save.
334 void xmlprops_set_property_b(
335 XmlProperty *props, const gchar *name, const gboolean value )
337 g_return_if_fail( props != NULL );
339 xmlprops_set_property( props, name, "y" );
342 xmlprops_set_property( props, name, "n" );
348 * Enter: props Property object.
349 * name Property name.
350 * Return: value found, or NULL if none. Should be g_free() when done.
352 gchar *xmlprops_get_property( XmlProperty *props, const gchar *name ) {
356 g_return_val_if_fail( props != NULL, value );
357 val = g_hash_table_lookup( props->propertyTable, name );
359 value = g_strdup( val );
365 * Get property into a buffer.
366 * Enter: props Property object.
367 * name Property name.
368 * Return: value found, or NULL if none. Should be g_free() when done.
370 void xmlprops_get_property_s(
371 XmlProperty *props, const gchar *name, gchar *buffer ) {
374 g_return_if_fail( props != NULL );
375 if( buffer == NULL ) return;
376 val = g_hash_table_lookup( props->propertyTable, name );
378 strcpy( buffer, val );
383 * Get property as integer value.
384 * Enter: props Property object.
385 * name Property name.
386 * Return: value found, or zero if not found.
388 gint xmlprops_get_property_i( XmlProperty *props, const gchar *name ) {
394 g_return_val_if_fail( props != NULL, value );
395 val = g_hash_table_lookup( props->propertyTable, name );
398 value = strtol( val, &endptr, 10 );
404 * Get property as boolean value.
405 * Enter: props Property object.
406 * name Property name.
407 * Return: value found, or FALSE if not found.
409 gboolean xmlprops_get_property_b( XmlProperty *props, const gchar *name ) {
414 g_return_val_if_fail( props != NULL, value );
415 val = g_hash_table_lookup( props->propertyTable, name );
417 value = ( g_strcasecmp( val, "y" ) == 0 );