#include #include #include #include #include #include "gm-options.h" #include "gm-string.h" #include "debug.h" extern int errno; #define GM_OPTIONS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GM_TYPE_OPTIONS, GmOptionsPrivate)) struct _GmOptionsPrivate { GHashTable *options; gchar *filepath; }; /* Signals */ enum { OPTION_CHANGED, NUM_SIGNALS }; static guint options_signals[NUM_SIGNALS] = {0}; G_DEFINE_TYPE(GmOptions, gm_options, G_TYPE_OBJECT) static void gm_options_finalize(GObject *object) { GmOptions *options = GM_OPTIONS(object); g_hash_table_destroy(options->priv->options); g_free(options->priv->filepath); G_OBJECT_CLASS(gm_options_parent_class)->finalize(object); } static void gm_options_class_init(GmOptionsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = gm_options_finalize; options_signals[OPTION_CHANGED] = g_signal_new("option_changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmOptionsClass, option_changed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private(object_class, sizeof(GmOptionsPrivate)); } static void gm_options_init(GmOptions *options) { options->priv = GM_OPTIONS_GET_PRIVATE(options); options->priv->options = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); options->priv->filepath = NULL; } GmOptions * gm_options_new(void) { GmOptions *options = GM_OPTIONS(g_object_new(GM_TYPE_OPTIONS, NULL)); return options; } void gm_options_dup_option(gchar *key, gchar *value, GmOptions *copy) { gm_options_set(copy, key, value); } GmOptions * gm_options_dup(GmOptions *source) { GmOptions *copy = gm_options_new(); g_hash_table_foreach(source->priv->options, (GHFunc)gm_options_dup_option, copy); return copy; } // Adds an option to opt, even if key already exists void gm_options_set(GmOptions * options, const gchar *key, const gchar *value) { gchar *trimmed = gm_string_trim(key); gboolean changed = g_hash_table_lookup(options->priv->options, trimmed) != NULL; g_hash_table_insert(options->priv->options, trimmed, g_strdup(value)); if (changed) { g_signal_emit(options, options_signals[OPTION_CHANGED], 0, key); } } const gchar * gm_options_get(GmOptions *options, const gchar *key) { return g_hash_table_lookup(options->priv->options, key); } void gm_options_set_int(GmOptions *options, const gchar *key, int value) { gchar val[15]; g_snprintf((gchar *) &val, 15, "%d", value); gm_options_set(options, key, (const gchar *) &val); } int gm_options_get_int(GmOptions *options, const gchar *key) { const gchar *val = gm_options_get(options, key); int ret; if (val && gm_string_to_int(val, &ret)) { return ret; } else { return 0; } } void gm_options_save_value(gchar *key, gchar *value, FILE *f) { debug_msg(1, "GmOptions.SaveValue: saving %s, %s", key, value); fprintf(f, "%s=%s\n", key, value); } void gm_options_save(GmOptions *options) { FILE *f; if (options->priv->filepath == NULL) { return; } f = fopen(options->priv->filepath, "w"); debug_msg(1, "GmOptions.save: saving options (%s)!", options->priv->filepath); if (f) { g_hash_table_foreach(options->priv->options, (GHFunc)gm_options_save_value, f); fclose(f); chmod(options->priv->filepath, 0660); } else { debug_msg(1, "GmOptions.save: couldn't open option file for saving: %s", strerror(errno)); } } void gm_options_save_as(GmOptions *options, const gchar *filename) { g_free(options->priv->filepath); options->priv->filepath = g_strdup(filename); gm_options_save(options); } void gm_options_load(GmOptions *options, const char *filename) { FILE *f; gchar **keyvalue, line[1024]; int i; debug_msg(1, "GmOptions.load: loading options (%s)!", filename); if ((f = fopen(filename, "r")) != NULL) { i = 0; while (fgets((char *) &line, 1024 - 1, f) != NULL) { line[strlen((char *) &line) - 1] = '\0'; i++; if (strlen(line) != 0) { // Empty lines, we don't need to process those keyvalue = g_strsplit(line, "=", 2); // This will return at least 1 element, at most 2, we need 2 if (strncmp(keyvalue[0], "#", 1) != 0) { // Commented lines, well ignore them too if (keyvalue[1] != NULL) { debug_msg(1, "GmOptions.load: adding %s, %s", keyvalue[0], keyvalue[1]); gm_options_set(options, keyvalue[0], keyvalue[1]); } else { debug_msg(1, "GmOptions.load: wrong syntax of options " "line in %s line %d", filename, i); } } g_strfreev(keyvalue); } } fclose(f); } else { debug_msg(1, "GmOptions.load: could not retrieve contents of file " "%s (%s)", filename, strerror(errno)); } g_free(options->priv->filepath); options->priv->filepath = g_strdup(filename); }