+2011-09-20 [mir] 0.6.0cvs17
+
+ * dbus-client/.cvsignore
+ * dbus-client/client.c
+ * plugins/xml/plugin-init.c
+ * plugins/xml/xml-plugin.c
+ * src/callbacks.c
+ * src/contactwindow.c
+ * src/gtk-utils.c
+ * src/gtk-utils.h
+ * src/plugin-loader.c
+ * src/plugin-loader.h
+ * src/plugin.h
+ * src/printing.c
+ * src/settings.c
+ * src/utils.c
+ * src/utils.h
+ * src/dbus/server-object.c
+ * xmllib/parser.c
+ Extended attribute support to use all available
+ supported attributes defined in AttribType.
+ Fix a lot of bugs and potential memory leaks.
+
+
2011-09-17 [mir] 0.6.0cvs16
* xmllib/parser.c
( cvs diff -u -r 1.1 -r 1.2 plugins/Makefile.am; diff -u /dev/null plugins/ldap/Makefile.am; diff -u /dev/null plugins/ldap/ldap-plugin.c; ) > 0.6.0cvs14.patchset
( diff -u /dev/null plugins/ldap/.cvsignore; ) > 0.6.0cvs15.patchset
( cvs diff -u -r 1.2 -r 1.3 xmllib/parser.c; ) > 0.6.0cvs16.patchset
+( cvs diff -u -r 1.1 -r 1.2 dbus-client/.cvsignore; cvs diff -u -r 1.1 -r 1.2 dbus-client/client.c; cvs diff -u -r 1.1 -r 1.2 plugins/xml/plugin-init.c; cvs diff -u -r 1.2 -r 1.3 plugins/xml/xml-plugin.c; cvs diff -u -r 1.2 -r 1.3 src/callbacks.c; cvs diff -u -r 1.1 -r 1.2 src/contactwindow.c; cvs diff -u -r 1.1 -r 1.2 src/gtk-utils.c; cvs diff -u -r 1.1 -r 1.2 src/gtk-utils.h; cvs diff -u -r 1.3 -r 1.4 src/plugin-loader.c; cvs diff -u -r 1.2 -r 1.3 src/plugin-loader.h; cvs diff -u -r 1.2 -r 1.3 src/plugin.h; cvs diff -u -r 1.1 -r 1.2 src/printing.c; cvs diff -u -r 1.1 -r 1.2 src/settings.c; cvs diff -u -r 1.1 -r 1.2 src/utils.c; cvs diff -u -r 1.1 -r 1.2 src/utils.h; cvs diff -u -r 1.1 -r 1.2 src/dbus/server-object.c; cvs diff -u -r 1.3 -r 1.4 xmllib/parser.c; ) > 0.6.0cvs17.patchset
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=16
+EXTRA_VERSION=17
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
*.la
claws-contacts
server-bindings.h
+client-bindings.h
+dbus-client
GValue email_member = {0};
gchar* str;
- contact->data = hash_table_new();
+ contact->data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
contact->emails = g_value_email_new();
firstname = lastname = NULL;
static GHashTable* get_attributes(
const gchar* path, gboolean old_abook, gchar** error) {
const gchar* header;
- const gchar **attribs;
-
+ AttribContainer* attribs;
+ GHashTable* result;
+
+ attribs = g_new0(AttribContainer, 1);
if (old_abook) {
header = native_header;
scanned_attribs = scan_existing_addrbooks(path, error);
- attribs = (const gchar**) scanned_attribs;
+ attribs->existing_attribs = (const gchar**) scanned_attribs;
}
else {
header = standard_header;
- attribs = standard_attribs;
+ attribs->existing_attribs = standard_attribs;
}
-
- return get_attrib_list(NULL, attribs, header, TRUE, error, add_attrib_btn_cb);
+
+ result = get_attrib_list(NULL, attribs, header, TRUE, error, add_attrib_btn_cb);
+ g_free(attribs);
+
+ return result;
}
GHashTable* plugin_get_attribs(gboolean* old_abook, gchar** error) {
static gchar self_home[] = "xml";
static gchar configrc[] = "xmlrc";
static ConfigFile* config = NULL;
+static GSList* inactive_attribs = NULL;
static void contact_set_uid(AddressBook* abook, Contact* contact) {
GHashTable* data = contact->data;
if (data) {
gchar* uid = g_strdup_printf("%ld", abook->next_uid);
abook->next_uid++;
- g_hash_table_replace(data, g_strdup("uid"), g_strdup(uid));
+ swap_data(data, "uid", uid);
g_free(uid);
}
}
static void abook_set_next_uid(AddressBook* abook) {
GList* cur;
gulong uid = 0;
+ gchar* id = NULL;
for (cur = abook->contacts; cur; cur = g_list_next(cur)) {
Contact* contact = (Contact *) cur->data;
if (contact && contact->data) {
- gchar* id = g_hash_table_lookup(contact->data, "uid");
+ extract_data(contact->data, "uid", (void **) &id);
gulong n = strtol(id, NULL, 10);
+ g_free(id);
uid = (n > uid) ? n : uid;
}
}
Image* image;
GSList* images = NULL, *cur1;
gboolean found;
+ gchar* uid = NULL;
dir = g_dir_open(dir_path, 0, &error);
if (!dir || error) {
for (cur2 = abook->contacts; !found && cur2; cur2 = g_list_next(cur2)) {
Contact* contact = (Contact *) cur2->data;
if (contact && contact->data) {
- gchar* uid = g_hash_table_lookup(contact->data, "uid");
+ extract_data(contact->data, "uid", (void **) &uid);
if (uid && strcmp(uid, image->uid) == 0) {
- g_hash_table_replace(contact->data,
- g_strdup("image"),
- g_strdup(image->image));
+ g_free(uid);
+ AttribDef* attr =
+ pack_data(ATTRIB_TYPE_STRING, "image", image->image);
+ g_hash_table_replace(contact->data, g_strdup("image"), attr);
found = TRUE;
}
uid = NULL;
g_free(image->image);
g_free(image);
}
- gslist_free(images, NULL);
+ gslist_free(&images, NULL);
}
static void abooks_free() {
}
}
-static gboolean person_attrib(gchar** str, gchar* key, gchar* value) {
+static gboolean person_attrib(gchar** str, gchar* key, AttribDef* attr) {
gchar *tmp, *k, *v;
if (strcasecmp("uid", key) == 0 ||
strcasecmp("cn", key) == 0) {
k = g_markup_escape_text(key, -1);
- v = g_markup_escape_text(value, -1);
+ v = g_markup_escape_text(attr->value.string, -1);
if (*str) {
tmp = g_strdup(*str);
g_free(*str);
return FALSE;
}
-static void attributes_attrib(gchar** str, gchar* key, gchar* value) {
+static void attributes_attrib(gchar** str, gchar* key, AttribDef* attr) {
gchar *tmp, *k, *v;
+ void* value = NULL;
+ AttribType type;
+ gboolean bool;
+ gchar ch;
+ gint i;
+ type = get_data(attr, &value);
+ switch (type) {
+ case ATTRIB_TYPE_BOOLEAN:
+ bool = *(gboolean *) value;
+ tmp = (bool) ? g_strdup("true") : g_strdup("false");
+ break;
+ case ATTRIB_TYPE_CHAR:
+ ch = *(gchar *) value;
+ tmp = g_strdup_printf("%c", ch);
+ break;
+ case ATTRIB_TYPE_INT:
+ i = *(gint *) value;
+ tmp = g_strdup_printf("%i", i);
+ break;
+ case ATTRIB_TYPE_STRING:
+ tmp = g_strdup((gchar *) value);
+ break;
+ }
+ g_free(value);
k = g_markup_escape_text(key, -1);
- v = g_markup_escape_text(value, -1);
+ v = g_markup_escape_text(tmp, -1);
+ g_free(tmp);
if (*str) {
tmp = g_strdup(*str);
g_free(*str);
g_hash_table_foreach(hash, hash_table_keys_to_slist, &attr);
for (cur = attr; cur; cur = g_slist_next(cur)) {
AttribDef* attrdef = (AttribDef *) cur->data;
- gchar* value = g_hash_table_lookup(hash, attrdef->attrib_name);
- if (person_attrib(&person, attrdef->attrib_name, value))
+ AttribDef* attr = g_hash_table_lookup(hash, attrdef->attrib_name);
+ if (person_attrib(&person, attrdef->attrib_name, attr))
continue;
- attributes_attrib(&attributes, attrdef->attrib_name, value);
+ attributes_attrib(&attributes, attrdef->attrib_name, attr);
}
- gslist_free(attr, attrib_def_free);
+ gslist_free(&attr, attrib_def_free);
for (mail = emails; mail; mail = g_slist_next(mail)) {
Email* email = (Email *) mail->data;
alias = g_markup_escape_text(email->alias, -1);
}
static void write_config_file(GSList** books) {
- GSList *cur, *tmp;
+ GSList *cur, *tmp, *cur_attribs;
gchar* error = NULL;
gchar* path = NULL;
g_slist_prepend(config->configured_books->books, g_strdup(book));
g_free(book);
}
- gslist_free(*books, NULL);
+ gslist_free(books, NULL);
*books = NULL;
plugin_config_set(config, &error);
}
cur = NULL;
- GSList* attribs = plugin_attrib_list();
- for (tmp = attribs; tmp; tmp = g_slist_next(tmp)) {
+ cur_attribs = plugin_attrib_list();
+ for (tmp = cur_attribs; tmp; tmp = g_slist_next(tmp)) {
AttribDef* attrdef = (AttribDef *) tmp->data;
cur = g_slist_prepend(cur, g_strdup(attrdef->attrib_name));
}
- gslist_free(attribs, attrib_def_free);
-
+ gslist_free(&cur_attribs, attrib_def_free);
config_set_value(config, "supported attributes", "attributes", cur);
- gslist_free(cur, g_free);
+ gslist_free(&cur, g_free);
+
+ cur = NULL;
+ cur_attribs = plugin_inactive_attribs();
+ for (tmp = cur_attribs; tmp; tmp = g_slist_next(tmp)) {
+ AttribDef* attrdef = (AttribDef *) tmp->data;
+ cur = g_slist_prepend(cur, g_strdup(attrdef->attrib_name));
+ }
+ gslist_free(&cur_attribs, attrib_def_free);
+ config_set_value(config, "deactivated attributes", "attributes", cur);
+ gslist_free(&cur, g_free);
}
static gint compare_book_names(gconstpointer a, gconstpointer b) {
static GSList* get_basic_attributes(Contact* contact) {
GSList *list = NULL, *cur;
+ gchar* value;
- list = g_slist_prepend(list,
- g_strdup(g_hash_table_lookup(contact->data, "nick-name")));
- list = g_slist_prepend(list,
- g_strdup(g_hash_table_lookup(contact->data, "first-name")));
- list = g_slist_prepend(list,
- g_strdup(g_hash_table_lookup(contact->data, "last-name")));
- list = g_slist_prepend(list,
- g_strdup(g_hash_table_lookup(contact->data, "cn")));
+ extract_data(contact->data, "nick-name", (void **) &value);
+ list = g_slist_prepend(list, g_strdup(value));
+ g_free(value);
+ extract_data(contact->data, "first-name", (void **) &value);
+ list = g_slist_prepend(list, g_strdup(value));
+ g_free(value);
+ extract_data(contact->data, "last-name", (void **) &value);
+ list = g_slist_prepend(list, g_strdup(value));
+ g_free(value);
+ extract_data(contact->data, "cn", (void **) &value);
+ list = g_slist_prepend(list, g_strdup(value));
+ g_free(value);
for (cur = contact->emails; cur; cur = g_slist_next(cur)) {
Email* e = (Email *) cur->data;
static void contact_compare_values(gpointer key, gpointer value, gpointer data) {
Compare* comp = (Compare *) data;
- gchar* cvalue;
+ AttribDef* attr;
if (debug_get_mode()) {
Contact* c = g_new0(Contact, 1);
}
if ((comp->is_and && comp->equal) ||
(!comp->is_and && (comp->equal < 0 || comp->equal == 0))) {
- cvalue = g_hash_table_lookup(comp->hash, key);
- comp->equal = match_string_pattern(value, cvalue, TRUE);
+ attr = g_hash_table_lookup(comp->hash, key);
+ if (attr) {
+ if (attr->type == ATTRIB_TYPE_STRING) {
+ comp->equal = match_string_pattern(
+ value, attr->value.string, TRUE);
+ }
+ else if (attr->type == ATTRIB_TYPE_CHAR) {
+ gchar* ch = g_strdup_printf("%c", attr->value.character);
+ comp->equal = match_string_pattern(value, ch, TRUE);
+ g_free(ch);
+ }
+ else {
+ /* TODO. How to compare int and boolean */
+ comp->equal = FALSE;
+ }
+ }
}
+ else
+ comp->equal = FALSE;
}
static gboolean email_compare_values(GSList* a, GSList* b, gboolean is_and) {
return equal;
}
+static void reactivate_attribs(gpointer key, gpointer value, gpointer data) {
+ GSList** new_list = (GSList**) data;
+ GSList *cur;
+ gboolean more = TRUE;
+
+ for (cur = inactive_attribs; cur && more; cur = g_slist_next(cur)) {
+ AttribDef* attr = (AttribDef *) cur->data;
+ if (utf8_collate(attr->attrib_name, (gchar *) key) == 0) {
+ *new_list = g_slist_remove(*new_list, attr);
+ attrib_def_free(attr);
+ more = FALSE;
+ }
+ }
+}
+
+static void deactivate_attribs(gpointer key, gpointer value, gpointer data) {
+ GHashTable* new_attr = (GHashTable *) data;
+
+ //hash_table_dump(new_attr, stderr);
+ if (! g_hash_table_lookup_extended(new_attr, key, NULL, NULL)) {
+ inactive_attribs = g_slist_prepend(inactive_attribs, attrib_def_copy(value));
+ }
+}
+
gboolean plugin_init(gchar** error) {
gchar *basedir, *path;
GSList *list = NULL, *cur, *found;
for (cur = list; cur; cur = g_slist_next(cur)) {
gchar* key = (gchar *) cur->data;
debug_print("Adding '%s' to attributes\n", key);
- g_hash_table_replace(attribs, g_strdup(key), NULL);
+ AttribDef* attr = g_new0(AttribDef, 1);
+ attr->attrib_name = g_strdup(key);
+ attr->type = ATTRIB_TYPE_STRING;
+ g_hash_table_replace(attribs, g_strdup(key), attr);
}
- gslist_free(list, g_free);
+ gslist_free(&list, g_free);
+
+ config_get_value(config, "deactivated attributes", "attributes", &list);
+ for (cur = list; cur; cur = g_slist_next(cur)) {
+ gchar* key = (gchar *) cur->data;
+ debug_print("Adding '%s' to deactivated attributes\n", key);
+ AttribDef* attr = g_new0(AttribDef, 1);
+ attr->attrib_name = g_strdup(key);
+ attr->type = ATTRIB_TYPE_STRING;
+ inactive_attribs = g_slist_prepend(inactive_attribs, attr);
+ }
+ gslist_free(&list, g_free);
+
+ //hash_table_dump(attribs, stderr);
}
}
g_free(basedir);
hash_table_free(&attribs);
abooks_free();
old_abook_free_dir();
+ gslist_free(&inactive_attribs, attrib_def_free);
return TRUE;
}
}
void plugin_attribs_set(GHashTable* attributes) {
+ GSList* new_list = gslist_deep_copy(inactive_attribs, attrib_def_copy);
+
+ //hash_table_dump(attributes, stderr);
+ g_hash_table_foreach(attributes, reactivate_attribs, &new_list);
+ gslist_free(&inactive_attribs, attrib_def_free);
+ inactive_attribs = gslist_deep_copy(new_list, attrib_def_copy);
+ gslist_free(&new_list, attrib_def_free);
+ g_hash_table_foreach(attribs, deactivate_attribs, attributes);
hash_table_free(&attribs);
attribs = hash_table_copy(attributes);
}
found = match_string_pattern(search_token, attr, FALSE);
}
}
- gslist_free(list, g_free);
+ gslist_free(&list, g_free);
if (found) {
contacts = g_slist_prepend(contacts, contact);
found = FALSE;
gboolean plugin_set_contact(
AddressBook* abook, const Contact* contact, gchar** error) {
+ gchar* uid = NULL;
- gchar* uid = g_hash_table_lookup(contact->data, "uid");
- if (! uid)
+ if (debug_get_mode())
+ contact_dump(contact, stderr);
+ extract_data(contact->data, "uid", (void **) &uid);
+ if (! uid || strlen(uid) < 1)
contact_set_uid(abook, (Contact *) contact);
+ g_free(uid);
addr_book_set_contact(abook, (Contact *) contact, error);
if (*error)
gboolean plugin_update_contact(
AddressBook* abook, const Contact* contact, gchar** error) {
+ if (debug_get_mode())
+ contact_dump(contact, stderr);
plugin_delete_contact(abook, contact, error);
if (*error)
return TRUE;
-
plugin_set_contact(abook, contact, error);
if (*error)
return TRUE;
gboolean plugin_commit_all(gchar** error) {
return TRUE;
}
+
+GSList* plugin_remaining_attribs(void) {
+ return NULL;
+}
+
+GSList* plugin_inactive_attribs(void) {
+ return gslist_deep_copy(inactive_attribs, attrib_def_copy);
+}
\ No newline at end of file
g_key_file_set_string_list(config->key_file, PLUGINGROUP,
"plugins", (const gchar**) list, num);
g_strfreev(list);
- gslist_free(plugins, g_free);
+ gslist_free(&plugins, g_free);
data = g_key_file_to_data(config->key_file, &len, &err);
if (! err) {
}
plugin_load_all(window, plugins);
- gslist_free(plugins, g_free);
- gslist_free(book, g_free);
+ gslist_free(&plugins, g_free);
+ gslist_free(&book, g_free);
g_free(configrc);
if (mainwindow)
Email* email = (Email *) contact->emails->data;
mail = email->email;
}
- first = g_hash_table_lookup(contact->data, "first-name");
- last = g_hash_table_lookup(contact->data, "last-name");
- cn = g_hash_table_lookup(contact->data, "cn");
+ extract_data(contact->data, "first-name", (void *) &first);
+ extract_data(contact->data, "last-name", (void *) &last);
+ extract_data(contact->data, "cn", (void *) &cn);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
CONTACT_EMAIL_COLUMN, mail,
CONTACT_DATA_COLUMN, contact,
-1);
+ g_free(first);
+ g_free(last);
+ g_free(cn);
}
gchar* contact_write_to_backend(Plugin* plugin,
gboolean response = show_choice_list(win->window,
"[Open book] Select plugin to use",
plugins, &plugin_name);
- gslist_free(plugins, NULL);
+ gslist_free(&plugins, NULL);
if (response) {
plugin = plugin_get_plugin(plugin_name);
gboolean response = show_choice_list(win->window,
"[New book] Select plugin to use",
plugins, &plugin_name);
- gslist_free(plugins, NULL);
+ gslist_free(&plugins, NULL);
if (response) {
plugin = plugin_get_plugin(plugin_name);
BOOK_DATA_COLUMN, book,
BOOK_PLUGIN_COLUMN, reference->plugin, -1);
}
- gslist_free(reference->abooks, NULL);
+ gslist_free(&reference->abooks, NULL);
}
if (! ref) {
gtk_widget_set_sensitive(mainwindow->search_btn, FALSE);
gtk_widget_set_sensitive(mainwindow->adv_search_btn, FALSE);
gtk_widget_set_sensitive(mainwindow->new_btn, FALSE);
}
- gslist_free(ref, NULL);
+ gslist_free(&ref, NULL);
}
void abook_list_cursor_changed_cb(GtkTreeView* tree_view, gpointer data) {
GSList* attribs = NULL;
gchar* error = NULL;
GHashTable* new_attribs = NULL;
+ AttribContainer* attr_container;
gint i;
plugins = plugin_get_name_all();
gboolean response = show_choice_list(win->window,
"[Attributes] Select plugin to use",
plugins, &plugin_name);
- gslist_free(plugins, NULL);
+ gslist_free(&plugins, NULL);
if (response) {
plugin = plugin_get_plugin(plugin_name);
+/*
if (plugin->readonly) {
show_message(win->window, GTK_UTIL_MESSAGE_INFO,
_("Plugin does not support updates"));
return;
}
+*/
if (plugin) {
attribs = plugin->attrib_list();
AttribDef* attrdef = (AttribDef *) cur->data;
attr[i] = g_strdup(attrdef->attrib_name);
}
- gslist_free(attribs, attrib_def_free);
- new_attribs = get_attrib_list(win->window, (const gchar**) attr,
- "Supported Attributes",
- TRUE, &error, add_attrib_btn_cb);
+ gslist_free(&attribs, attrib_def_free);
+ attribs = plugin->inactive_attribs();
+ gchar** inactive_attr = g_new0(gchar *, g_slist_length(attribs) + 1);
+ for (cur = attribs, i = 0; cur; i++, cur = g_slist_next(cur)) {
+ AttribDef* attrdef = (AttribDef *) cur->data;
+ inactive_attr[i] = g_strdup(attrdef->attrib_name);
+ }
+ gslist_free(&attribs, attrib_def_free);
+ attr_container = g_new0(AttribContainer, 1);
+ attr_container->existing_attribs = (const gchar**) attr;
+ attr_container->inactive_attribs = (const gchar **) inactive_attr;
+ new_attribs = get_attrib_list(win->window, attr_container,
+ "Supported Attributes", TRUE, &error, add_attrib_btn_cb);
g_strfreev(attr);
+ g_strfreev(inactive_attr);
+ g_free(attr_container);
if (error) {
show_message(win->window, GTK_UTIL_MESSAGE_ERROR, "%s", error);
g_free(error);
}
else {
+ //hash_table_dump(new_attribs, stderr);
plugin->attribs_set(new_attribs);
}
hash_table_free(&new_attribs);
list_view_append_contact(view, contact);
}
}
- gslist_free(contacts, NULL);
+ gslist_free(&contacts, NULL);
}
}
}
gtk_widget_set_sensitive(win->clear_btn, TRUE);
}
- gslist_free(contacts, NULL);
+ gslist_free(&contacts, NULL);
}
else
static gboolean contact_is_new = FALSE;
static void email_list_add(GtkTreeView* view, ContactWindow* cw);
+static gchar* hash_table_get_entry(GHashTable* hash, const gchar* key);
static void contact_entry_data_update(ContactWindow* cw) {
gint i;
static gboolean entry_dirty(GHashTable* hash,
const gchar* key,
const gchar* new_data) {
- gchar* old_data =
- g_hash_table_lookup(hash, key);
+ gchar* value = NULL;
- return (xor(old_data, new_data));
+ value = hash_table_get_entry(hash, key);
+ gboolean res = xor(value, new_data);
+
+ g_free(value);
+
+ return res;
}
static gboolean contact_dirty(ContactEntryData** data) {
gboolean changed = FALSE;
Contact *contact, *cur = NULL;
const gchar* new_data;
+ void* value = NULL;
+ AttribDef* attr;
+ gchar* tmp = NULL;
+ gboolean bool;
+ gchar ch;
+ gint num;
contact = cw->contact;
for (i = 0; i < contact_entry_data_size; i++) {
cur = cw->data[i]->contact;
if (cur && cur->data && cw->data[i]->key) {
- gchar* old_data =
- g_hash_table_lookup(cur->data, cw->data[i]->key);
+ attr = g_hash_table_lookup(cur->data, cw->data[i]->key);
+ if (attr) {
+ AttribType type = get_data(attr, &value);
+ switch (type) {
+ case ATTRIB_TYPE_BOOLEAN:
+ bool = *(gboolean *) value;
+ tmp = (bool) ? g_strdup("true") : g_strdup("false");
+ break;
+ case ATTRIB_TYPE_CHAR:
+ ch = *(gchar *) value;
+ tmp = g_strdup_printf("%c", ch);
+ break;
+ case ATTRIB_TYPE_INT:
+ num = *(gint *) value;
+ tmp = g_strdup_printf("%i", num);
+ break;
+ case ATTRIB_TYPE_STRING:
+ tmp = g_strdup((gchar *) value);
+ break;
+ }
+ g_free(value);
+ }
if (cw->data[i]->entry)
new_data = gtk_entry_get_text(GTK_ENTRY(cw->data[i]->entry));
else
new_data = NULL;
- if (xor(old_data, new_data)) {
- g_hash_table_replace(contact->data,
- g_strdup(cw->data[i]->key), g_strdup(new_data));
+ if (xor(tmp, new_data)) {
+ swap_data(contact->data, cw->data[i]->key, new_data);
changed = TRUE;
}
+ g_free(tmp);
+ tmp = NULL;
}
}
email_list_add(GTK_TREE_VIEW(cw->email_list), cw);
cur = NULL;
cur = g_slist_prepend(cur, remove);
- gslist_free(cur, g_free);
+ gslist_free(&cur, g_free);
}
}
}
}
static gchar* hash_table_get_entry(GHashTable* hash, const gchar* key) {
- gchar* value;
+ AttribDef* attr;
+ gchar* value = NULL;
- value = g_hash_table_lookup(hash, key);
+ attr = g_hash_table_lookup(hash, key);
- return (value) ? value : "";
+ if (attr) {
+ switch (attr->type) {
+ case ATTRIB_TYPE_BOOLEAN:
+ value = (attr->value.boolean) ? g_strdup("true") : g_strdup("false");
+ break;
+ case ATTRIB_TYPE_INT:
+ value = g_new0(gchar, 5);
+ sprintf(value, "%i", attr->value.number);
+ break;
+ case ATTRIB_TYPE_CHAR:
+ value = g_new0(gchar, 1);
+ sprintf(value, "%c", attr->value.character);
+ break;
+ case ATTRIB_TYPE_STRING:
+ value = g_strdup(attr->value.string);
+ break;
+ }
+ }
+ return (value) ? value : g_strdup("");
}
static void contact_image_change(gpointer data) {
if (pixbuf) {
gchar* image = base64_encode_data(file);
- g_hash_table_replace(cw->contact->data,
- g_strdup("image"), g_strdup(image));
+ swap_data(cw->contact->data, "image", image);
g_free(image);
GtkWidget* parent = gtk_widget_get_parent(cw->image);
gtk_widget_destroy(cw->image);
if (hash)
value = hash_table_get_entry(hash, data->key);
else
- value = "";
+ value = g_strdup("");
gtk_entry_set_text(GTK_ENTRY(entry), value);
+ g_free(value);
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
gchar* s = gtk_tree_path_to_string(path);
debug_print("deleted: %s\n", s);
g_free(s);
- gslist_free(cw->contact->emails, email_free);
+ gslist_free(&cw->contact->emails, email_free);
cw->contact->emails = NULL;
gtk_tree_model_foreach(tree_model, contact_reorder_emails, cw);
contact_update(cw, cw->contact);
gtk_frame_set_label_widget(GTK_FRAME(frame), label_photo);
if (cw->contact->data) {
- photo = g_hash_table_lookup(cw->contact->data, "image");
- if (photo) {
- pixbuf = contact_load_image(cw->main->window, photo);
- if (! pixbuf)
- photo = NULL;
+ if (debug_get_mode())
+ contact_dump(cw->contact, stderr);
+ AttribDef* attr = g_hash_table_lookup(cw->contact->data, "image");
+ if (attr) {
+ photo = attr->value.string;
+ if (photo) {
+ pixbuf = contact_load_image(cw->main->window, photo);
+ if (! pixbuf)
+ photo = NULL;
+ }
}
}
email->remarks = g_strdup(value);
}
else
- g_hash_table_replace(
- contact->data, g_strdup(data[i]->key), g_strdup(value));
+ swap_data(contact->data, data[i]->key, value);
}
}
}
AttribDef* attrdef = g_slist_nth_data(attr, i);
dialog->data[i]->key = g_strdup(attrdef->attrib_name);
}
- gslist_free(attr, attrib_def_free);
+ gslist_free(&attr, attrib_def_free);
if (! dialog->contact) {
contact_is_new = TRUE;
gtk_widget_set_tooltip_text(row, tooltip);
gtk_box_pack_start(vbox, row, FALSE, TRUE, 0);
}
- gslist_free(attr, attrib_def_free);
+ gslist_free(&attr, attrib_def_free);
data[pos] = g_new0(ContactEntryData, 1);
data[pos]->key = g_strdup("alias");
g_message("%s", err);
g_free(err);
err = NULL;
- gslist_free(result, NULL);
- result = NULL;
+ gslist_free(&result, NULL);
return;
}
for (contacts = result; contacts; contacts = g_slist_next(contacts)) {
g_ptr_array_add(array, g_strdup(text[i]));
g_strfreev(text);
}
- gslist_free(result, NULL);
+ gslist_free(&result, NULL);
plugin->abook_close(abook, &err);
}
list = g_slist_prepend(list, g_strdup(ab->abook_name));
}
}
- gslist_free(abooks, NULL);
+ gslist_free(&abooks, NULL);
*books = gslist_to_array(list, NULL);
- gslist_free(list, g_free);
+ gslist_free(&list, g_free);
return response;
}
debug_print("%s", *reply);
g_message("End receive");
- gslist_free(abooks, NULL);
+ gslist_free(&abooks, NULL);
return response;
}
g_free(config);
if (default_book) {
search_book = g_strdup((gchar *) default_book->data);
- gslist_free(default_book, g_free);
+ gslist_free(&default_book, g_free);
}
if (! search_book) {
g_set_error(error,
#include "gtk-utils.h"
#include "utils.h"
#include "plugin-loader.h"
+#include "plugin.h"
typedef struct {
GHashTable* hash_table;
gchar* error;
} CallbackData;
+typedef struct {
+ GtkWidget* parent;
+ GtkWidget* vbox;
+} ButtonCB;
+
+
static void callback_data_free(CallbackData* data) {
hash_table_free(&data->hash_table);
g_free(data->error);
GtkWidget* btn;
const gchar* label;
gboolean use;
+ AttribDef* attr;
btn = gtk_bin_get_child(GTK_BIN(widget));
if (btn) {
use = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn));
if (use) {
label = gtk_button_get_label(GTK_BUTTON(btn));
+ attr = g_new0(AttribDef, 1);
+ attr->attrib_name = g_strdup(label);
+ attr->type = ATTRIB_TYPE_STRING;
g_hash_table_replace(
- callback_data->hash_table, g_strdup(label), NULL);
+ callback_data->hash_table, g_strdup(label), attr);
}
}
}
}
GHashTable* get_attrib_list(GtkWidget* parent,
- const gchar **existing_attribs,
+ AttribContainer* attrib_lists,
const gchar* info_text, gboolean can_delete,
gchar** error, AddAttribCallback callback) {
GtkWidget *header, *dialog, *window, *vbox1, *attrib_box,
gint i;
GHashTable* hash_table = NULL;
CallbackData* callback_data;
+ ButtonCB* button_cb;
+ if (! attrib_lists ||
+ (! attrib_lists->existing_attribs && ! attrib_lists->inactive_attribs))
+ return NULL;
+
callback_data = g_new0(CallbackData, 1);
callback_data->hash_table = hash_table_new();
callback_data->error = NULL;
gtk_scrolled_window_add_with_viewport(
GTK_SCROLLED_WINDOW(window), attrib_box);
- for(i = 0; existing_attribs[i]; i++) {
- GtkWidget* check_btn = gtk_check_button_new_with_label(existing_attribs[i]);
+ for(i = 0; attrib_lists->existing_attribs[i]; i++) {
+ GtkWidget* check_btn = gtk_check_button_new_with_label(
+ attrib_lists->existing_attribs[i]);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_btn), TRUE);
gtk_widget_set_sensitive(check_btn, can_delete);
GtkWidget* frame = gtk_frame_new(NULL);
gtk_box_pack_start(GTK_BOX(attrib_box), frame, FALSE, TRUE, 0);
}
+ if (attrib_lists->inactive_attribs && *attrib_lists->inactive_attribs) {
+ for(i = 0; attrib_lists->inactive_attribs[i]; i++) {
+ GtkWidget* check_btn = gtk_check_button_new_with_label(
+ attrib_lists->inactive_attribs[i]);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_btn), FALSE);
+ gtk_widget_set_sensitive(check_btn, can_delete);
+ GtkWidget* frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(frame), check_btn);
+ gtk_box_pack_start(GTK_BOX(attrib_box), frame, FALSE, TRUE, 0);
+ }
+ }
+
gtk_box_pack_start(GTK_BOX(vbox1), frame2, TRUE, TRUE, 0);
hbtnbox = gtk_hbutton_box_new();
gtk_button_box_set_layout(GTK_BUTTON_BOX(hbtnbox), GTK_BUTTONBOX_CENTER);
add_attrib_btn = gtk_button_new_with_mnemonic("_Add attribute");
gtk_box_pack_start_defaults(GTK_BOX(hbtnbox), add_attrib_btn);
+ button_cb = g_new0(ButtonCB, 1);
+ button_cb->parent = parent;
+ button_cb->vbox = attrib_box;
g_signal_connect(
- add_attrib_btn, "clicked", G_CALLBACK(callback), attrib_box);
+ add_attrib_btn, "clicked", G_CALLBACK(callback), button_cb);
gtk_box_pack_start(GTK_BOX(vbox1), hbtnbox, FALSE, TRUE, 0);
gtk_widget_show_all(vbox1);
}
break;
default:
- for(i = 0; existing_attribs[i]; i++) {
+ for(i = 0; attrib_lists->existing_attribs[i]; i++) {
+ AttribDef* attr = g_new0(AttribDef, 1);
+ attr->attrib_name = g_strdup(attrib_lists->existing_attribs[i]);
+ attr->type = ATTRIB_TYPE_STRING;
g_hash_table_replace(callback_data->hash_table,
- g_strdup(existing_attribs[i]), NULL);
+ g_strdup(attrib_lists->existing_attribs[i]), attr);
}
hash_table = hash_table_copy(callback_data->hash_table);
break;
}
gtk_widget_destroy(dialog);
+ g_free(button_cb);
callback_data_free(callback_data);
return hash_table;
gtk_box_reorder_child(GTK_BOX(vbox), frame, 0);
}
-void add_attrib_btn_cb(GtkWidget* parent, GtkWidget* widget, gpointer data) {
- GtkWidget* vbox = (GtkWidget *) data;
+void add_attrib_btn_cb(GtkWidget* widget, gpointer data) {
+ ButtonCB* button_cb = (ButtonCB *) data;
gchar* reply = NULL;
if (show_input(
- parent, "Define new attribute", &reply, "Enter name for new attribute")) {
+ button_cb->parent, "Define new attribute",
+ &reply, "Enter name for new attribute")) {
GtkWidget* check_btn = gtk_check_button_new_with_label(reply);
g_free(reply);
gtk_widget_show(check_btn);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_btn), TRUE);
- add_widget_attrib_list(vbox, check_btn);
+ add_widget_attrib_list(button_cb->vbox, check_btn);
}
}
gchar* name;
} RowData;
+/*
struct RowContainer {
GSList* rows;
};
+*/
+
+typedef struct {
+ const gchar **existing_attribs;
+ const gchar **inactive_attribs;
+ const gchar **remaining_attribs;
+} AttribContainer;
-typedef void (*AddAttribCallback) (GtkWidget* parent, GtkWidget* widget, gpointer data);
+typedef void (*AddAttribCallback) (GtkWidget* widget, gpointer data);
void show_message(GtkWidget* parent, MessageType type, const gchar* format, ...);
gboolean show_question(GtkWidget* parent, const gchar* format, ...);
gboolean show_input(GtkWidget* parent, const gchar* title,
gchar** reply, const gchar* format, ...);
GHashTable* get_attrib_list(GtkWidget* parent,
- const gchar **existing_attribs,
+ AttribContainer* attrib_lists,
const gchar* info_text, gboolean can_delete,
gchar** error, AddAttribCallback callback);
void add_widget_attrib_list(GtkWidget* vbox, GtkWidget* check_btn);
-void add_attrib_btn_cb(GtkWidget* parent, GtkWidget* widget, gpointer data);
+void add_attrib_btn_cb(GtkWidget* widget, gpointer data);
gboolean show_choice_list(GtkWidget* parent,
const gchar* title,
GSList* choices,
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
gtk_tree_selection_select_iter(selection, &iter);
- gslist_free(loaded, NULL);
- gslist_free(unloaded, NULL);
+ gslist_free(&loaded, NULL);
+ gslist_free(&unloaded, NULL);
}
static void load_plugin_cb(GtkWidget* widget, gpointer data) {
set_plugin_list(pluginwindow);
g_free(file);
}
- gslist_free(files, NULL);
+ gslist_free(&files, NULL);
}
}
else
break;
}
}
- gslist_free(plugins, NULL);
+ gslist_free(&plugins, NULL);
if (! found) {
plugins = plugin_get_unloaded_list();
break;
}
}
- gslist_free(plugins, NULL);
+ gslist_free(&plugins, NULL);
if (found) {
g_free(found->error);
get_contact, set_contact, delete_contact, search_contact, update_contact,
plugin_abook_open, plugin_abook_close, plugin_abook_delete,
plugin_addrbook_all_get, plugin_abook_set_config, plugin_type,
- plugin_url, plugin_attribs_set, plugin_commit_all;
+ plugin_url, plugin_attribs_set, plugin_commit_all,
+ plugin_remaining_attribs, plugin_inactive_attribs;
plugin = g_new0(Plugin, 1);
if (plugin == NULL) {
!g_module_symbol(plugin->module, "plugin_abook_delete", &plugin_abook_delete) ||
!g_module_symbol(plugin->module, "plugin_abook_set_config", &plugin_abook_set_config) ||
!g_module_symbol(plugin->module, "plugin_commit_all", &plugin_commit_all) ||
- !g_module_symbol(plugin->module, "plugin_init", &plugin_init)) {
+ !g_module_symbol(plugin->module, "plugin_init", &plugin_init) ||
+ !g_module_symbol(plugin->module, "plugin_remaining_attribs", &plugin_remaining_attribs) ||
+ !g_module_symbol(plugin->module, "plugin_inactive_attribs", &plugin_inactive_attribs)) {
*error = g_strdup(g_module_error());
g_module_close(plugin->module);
g_free(plugin);
plugin->abook_set_config = plugin_abook_set_config;
plugin->default_url = plugin_url;
plugin->abooks_commit_all = plugin_commit_all;
+ plugin->remaining_attribs = plugin_remaining_attribs;
+ plugin->inactive_attribs = plugin_inactive_attribs;
compute_hash(plugin);
plugin_unload(plugin);
}
- gslist_free(plugins, NULL);
- gslist_free(unloaded_plugins, NULL);
- gslist_free(loaded, NULL);
- gslist_free(unloaded, NULL);
+ gslist_free(&plugins, NULL);
+ gslist_free(&unloaded_plugins, NULL);
+ gslist_free(&loaded, NULL);
+ gslist_free(&unloaded, NULL);
}
GSList* plugin_get_name_all() {
Plugin *plugin = (Plugin *) cur->data;
names = g_slist_prepend(names, g_strdup(plugin->name()));
}
- gslist_free(loaded, NULL);
+ gslist_free(&loaded, NULL);
return names;
}
Plugin *plugin = (Plugin *) cur->data;
names = g_slist_prepend(names, g_strdup(plugin->filename));
}
- gslist_free(loaded, NULL);
+ gslist_free(&loaded, NULL);
return names;
}
ref->abooks = ref->plugin->addrbook_all_get();
addr_books = g_slist_prepend(addr_books, ref);
}
- gslist_free(loaded, NULL);
+ gslist_free(&loaded, NULL);
return addr_books;
}
break;
plugin = NULL;
}
- gslist_free(loaded, NULL);
+ gslist_free(&loaded, NULL);
return plugin;
}
found_book = TRUE;
}
}
- gslist_free(books, NULL);
+ gslist_free(&books, NULL);
return (found_book) ? ref : NULL;
}
const gchar* (*license) (void);
const gchar* (*filter) (void);
gchar* (*default_url) (const gchar* name);
+ GSList* (*remaining_attribs) (void);
+ GSList* (*inactive_attribs) (void);
PluginFeature* (*provides) (void);
GSList* (*attrib_list) (void);
void (*attribs_set) (GHashTable* attributes);
typedef enum {
ATTRIB_TYPE_INT,
- ATTRIB_TYPE_CHAR,
ATTRIB_TYPE_BOOLEAN,
+ ATTRIB_TYPE_CHAR,
ATTRIB_TYPE_STRING
} AttribType;
+typedef union {
+ gint number;
+ gboolean boolean;
+ gchar character;
+ gchar* string;
+} Value;
+
typedef struct {
- gchar* attrib_name;
AttribType type;
+ gchar* attrib_name;
+ Value value;
} AttribDef;
typedef struct {
const gchar* plugin_type(void);
const gchar* plugin_license(void);
gchar* plugin_default_url(const gchar* name);
+GSList* plugin_remaining_attribs(void);
+GSList* plugin_inactive_attribs(void);
+
gboolean plugin_abook_open(AddressBook* abook, gchar** error);
gboolean plugin_abook_close(AddressBook* abook, gchar** error);
gboolean plugin_abook_delete(AddressBook* abook, gchar** error);
static void contact_get_data(gpointer key, gpointer value, gpointer data) {
PrintData* pd = (PrintData *) data;
gchar *k, *v;
+ void* val = NULL;
+ gboolean bool;
+ gchar ch;
+ gint i;
k = (gchar *) key;
- v = (gchar *) value;
+ AttribType type = get_data((AttribDef *) value, &val);
+ switch (type) {
+ case ATTRIB_TYPE_BOOLEAN:
+ bool = *(gboolean *) val;
+ v = (bool) ? g_strdup("true") : g_strdup("false");
+ break;
+ case ATTRIB_TYPE_CHAR:
+ ch = *(gchar *) val;
+ v = g_strdup_printf("%c", ch);
+ break;
+ case ATTRIB_TYPE_INT:
+ i = *(gint *) val;
+ v = g_strdup_printf("%i", i);
+ break;
+ case ATTRIB_TYPE_STRING:
+ v = g_strdup((gchar *) val);
+ break;
+ }
+ g_free(val);
+
if (strcmp(k, "uid") != 0 && strcmp(k, "image") != 0 &&
strlen(k) > 0 && strlen(v) > 0) {
pd->lines[pd->total_lines++] = g_strdup_printf("%s: %s", k, v);
pd->lines = g_renew(gchar *, pd->lines, pd->total_lines + 1);
pd->lines[pd->total_lines] = NULL;
}
+ g_free(v);
}
static void email_get_data(GSList* emails, PrintData* pd) {
PrintData* pd = (PrintData *) data;
g_strfreev(pd->lines);
- gslist_free(pd->contacts, NULL);
+ gslist_free(&pd->contacts, NULL);
g_free(pd);
}
g_free(name);
config_set_value(config, "Settings", "default book", list);
- gslist_free(list, g_free);
+ gslist_free(&list, g_free);
update_abook_list(win);
}
gpointer user_data) {
GHashTable* hash = (GHashTable *) user_data;
- debug_print("Key: %s - Value: %s\n", key, value);
- g_hash_table_replace(hash, g_strdup(key), g_strdup(value));
+ debug_print("Key: %s - Value: %p\n", key, value);
+ g_hash_table_replace(hash, g_strdup(key), attrib_def_copy(value));
}
/*
return g_strconcat(get_home(), G_DIR_SEPARATOR_S, self_home, NULL);
}
-void gslist_free(GSList* list, void (*elem_free) (gpointer data)) {
+void gslist_free(GSList** list, void (*elem_free) (gpointer data)) {
GSList* cur;
- if (list == NULL)
+ if (!list || !*list)
return;
if (elem_free) {
- for (cur = list; cur; cur = g_slist_next(cur)) {
+ for (cur = *list; cur; cur = g_slist_next(cur)) {
elem_free(cur->data);
+ cur->data = NULL;
}
}
- g_slist_free(list);
+ g_slist_free(*list);
+ *list = NULL;
}
void hash_table_free(GHashTable** hash_table) {
GHashTable* hash_table_new(void) {
GHashTable* hash_table;
- hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ hash_table = g_hash_table_new_full(
+ g_str_hash, g_str_equal, g_free, attrib_def_free);
return hash_table;
}
void attrib_def_free(gpointer attrdef) {
AttribDef* a = (AttribDef *) attrdef;
- g_free(a->attrib_name);
+ if (a->attrib_name) {
+ g_free(a->attrib_name);
+ a->attrib_name = NULL;
+ }
+ if (a->type == ATTRIB_TYPE_STRING && a->value.string) {
+ g_free(a->value.string);
+ a->value.string = NULL;
+ }
g_free(a);
+ a = NULL;
+}
+
+gpointer attrib_def_copy(gpointer a) {
+ AttribDef* a1;
+ AttribDef* a2;
+
+ if (!a)
+ return NULL;
+
+ a1 = g_new0(AttribDef, 1);
+ a2 = (AttribDef *) a;
+
+ if (a2->attrib_name)
+ a1->attrib_name = g_strdup(a2->attrib_name);
+ a1->type = a2->type;
+ if (a2->type == ATTRIB_TYPE_STRING)
+ a1->value.string = g_strdup(a2->value.string);
+ else
+ a1->value = a2->value;
+
+ return (gpointer) a1;
}
void hash_table_keys_to_slist(gpointer key, gpointer value, gpointer slist) {
g_free(config->comment);
if (cf_books) {
g_free(cf_books->group);
- gslist_free(cf_books->books, g_free);
+ gslist_free(&cf_books->books, g_free);
g_free(cf_books);
cf_books = NULL;
}
if (cl_books) {
g_free(cl_books->group);
- gslist_free(cl_books->books, g_free);
+ gslist_free(&cl_books->books, g_free);
g_free(cl_books);
cl_books = NULL;
}
if (debug_get_mode())
contact_dump(c, stderr);
hash_table_free(&c->data);
- gslist_free(c->emails, email_free);
+ gslist_free(&c->emails, email_free);
}
AddressBook* address_book_get(Plugin* plugin, const gchar* name) {
abook = NULL;
}
- gslist_free(books, NULL);
+ gslist_free(&books, NULL);
return abook;
}
gboolean contact_compare_attrib(Contact* a, Contact* b, const AttribDef* compare) {
gboolean result = FALSE;
- gpointer a_id, b_id;
+ AttribDef *a_id, *b_id;
gint res;
if (!a || !a->data || !b || !b->data || !compare || !compare->attrib_name)
return result;
- a_id = g_hash_table_lookup(a->data, compare->attrib_name);
- b_id = g_hash_table_lookup(b->data, compare->attrib_name);
+ a_id = (AttribDef *) g_hash_table_lookup(a->data, compare->attrib_name);
+ b_id = (AttribDef *) g_hash_table_lookup(b->data, compare->attrib_name);
if (!a_id || !b_id)
return result;
switch (compare->type) {
case ATTRIB_TYPE_BOOLEAN:
+ result = a_id->value.boolean == b_id->value.boolean;
+ break;
case ATTRIB_TYPE_INT:
- result = GPOINTER_TO_INT(a_id) == GPOINTER_TO_INT(b_id);
+ result = a_id->value.number == b_id->value.number;
break;
case ATTRIB_TYPE_CHAR:
- result = (gchar *) a_id == (gchar *) b_id;
+ result = a_id->value.character == b_id->value.character;
break;
case ATTRIB_TYPE_STRING:
- res = g_utf8_collate((gchar *) a_id, (gchar *) b_id);
+ res = g_utf8_collate(a_id->value.string, b_id->value.string);
result = (res == 0);
}
void contact_data_print(gpointer key, gpointer value, gpointer data) {
FILE* f = (FILE *) data;
-
+ AttribDef* attr = (AttribDef *) value;
+ gchar* val = NULL;
+
+ if (attr) {
+ switch (attr->type) {
+ case ATTRIB_TYPE_BOOLEAN:
+ val = (attr->value.boolean) ? g_strdup("true") : g_strdup("false");
+ break;
+ case ATTRIB_TYPE_INT:
+ val = g_strdup_printf("%i", attr->value.number);
+ break;
+ case ATTRIB_TYPE_CHAR:
+ val = g_strdup_printf("%c", attr->value.character);
+ break;
+ case ATTRIB_TYPE_STRING:
+ val = g_strdup(attr->value.string);
+ break;
+ }
+ }
+
if (f)
- fprintf(f, "Key: %s - Value: %s\n", (gchar *) key, (gchar *) value);
+ fprintf(f, "Key: %s - Value: %s\n", (gchar *) key, val);
else
- g_message("Key: %s - Value: %s", (gchar *) key, (gchar *) value);
+ g_message("Key: %s - Value: %s", (gchar *) key, val);
+
+ g_free(val);
}
void contact_dump(Contact* contact, FILE* f) {
if (utf8_collate(def->attrib_name, (gchar *) attribute) == 0)
found = TRUE;
}
- gslist_free(attribs, attrib_def_free);
+ gslist_free(&attribs, attrib_def_free);
return found;
}
+
+GSList* gslist_deep_copy(GSList* list, COPYFUNC copy_func) {
+ GSList *new = NULL, *cur;
+
+ if (!copy_func || !list)
+ return new;
+
+ for (cur = list; cur; cur = g_slist_next(cur)) {
+ new = g_slist_prepend(new, copy_func(cur->data));
+ }
+
+ return new;
+}
+
+static void hash_print(gpointer key, gpointer value, gpointer data) {
+ FILE* f = (FILE *) data;
+ AttribDef* attr = (AttribDef *) value;
+ const gchar* type;
+
+ switch (attr->type) {
+ case ATTRIB_TYPE_INT: type = "INT"; break;
+ case ATTRIB_TYPE_CHAR: type = "CHAR"; break;
+ case ATTRIB_TYPE_BOOLEAN: type = "BOOLEAN"; break;
+ case ATTRIB_TYPE_STRING: type = "STRING"; break;
+ }
+
+ fprintf(f, "key: %s\n\tname: %s\n\ttype: %s\n",
+ (gchar *) key, attr->attrib_name, type);
+}
+
+void hash_table_dump(GHashTable* hash, FILE* f) {
+ if (!hash || !f)
+ return;
+
+ g_hash_table_foreach(hash, hash_print, (gpointer) f);
+}
+
+AttribDef* pack_data(AttribType type, const gchar* name, const void* value) {
+ AttribDef* data;
+
+ data = g_new0(AttribDef, 1);
+ data->type = type;
+ if (name)
+ data->attrib_name = g_strdup(name);
+ switch (type) {
+ case ATTRIB_TYPE_INT:
+ data->value.number = *(gint *) value;
+ break;
+ case ATTRIB_TYPE_BOOLEAN:
+ data->value.boolean = *(gboolean *) value;
+ break;
+ case ATTRIB_TYPE_CHAR:
+ data->value.character = *(char *) value;
+ break;
+ case ATTRIB_TYPE_STRING:
+ data->value.string = g_strdup((const gchar *) value);
+ break;
+ }
+
+ return data;
+}
+
+void extract_data(GHashTable* data, const gchar* key, void** value) {
+ AttribDef* attr;
+
+ if (! data || ! key || ! value)
+ return;
+
+ attr = g_hash_table_lookup(data, key);
+ if (attr) {
+ get_data(attr, value);
+ }
+}
+
+void swap_data(GHashTable* data, const gchar* key, void* value) {
+ AttribDef* attr;
+
+ if (! data || ! key || ! value)
+ return;
+
+ attr = g_hash_table_lookup(data, key);
+
+ if (attr) {
+ switch (attr->type) {
+ case ATTRIB_TYPE_INT:
+ attr->value.number = *(gint *) value;
+ break;
+ case ATTRIB_TYPE_BOOLEAN:
+ attr->value.boolean = *(gboolean *) value;
+ break;
+ case ATTRIB_TYPE_CHAR:
+ attr->value.character = *(char *) value;
+ break;
+ case ATTRIB_TYPE_STRING:
+ g_free(attr->value.string);
+ attr->value.string = g_strdup(value);
+ break;
+ }
+ }
+ else {
+ attr = pack_data(ATTRIB_TYPE_STRING, key, (gchar *) value);
+ g_hash_table_replace(data, g_strdup(key), attr);
+ }
+}
+
+AttribType get_data(AttribDef* attrib_def, void** value) {
+ if (attrib_def && value) {
+ switch (attrib_def->type) {
+ case ATTRIB_TYPE_INT:
+ *value = &attrib_def->value.number;
+ break;
+ case ATTRIB_TYPE_BOOLEAN:
+ *value = &attrib_def->value.boolean;
+ break;
+ case ATTRIB_TYPE_CHAR:
+ *value = &attrib_def->value.character;
+ break;
+ case ATTRIB_TYPE_STRING:
+ *value = g_strdup(attrib_def->value.string);
+ break;
+ }
+ }
+
+ return attrib_def->type;
+}
\ No newline at end of file
debug_print_real("%s:%d:[%s]: ", debug_srcname(__FILE__), __LINE__, ___FUNC___), \
debug_print_real
+typedef gpointer (*COPYFUNC) (gpointer);
+
void debug_print_real(const gchar *format, ...);
const char* debug_srcname(const char *file);
gboolean debug_get_mode();
gboolean first_time(const gchar* subpath, const gchar* config, gchar** error);
void close_log_file();
+void swap_data(GHashTable* data, const gchar* key, void* value);
+AttribDef* pack_data(AttribType type, const gchar* name, const void* value);
+void extract_data(GHashTable* data, const gchar* key, void** value);
+AttribType get_data(AttribDef* attrib_def, void** value);
void attrib_def_free(gpointer attrdef);
-void gslist_free(GSList* list, void (*elem_free) (gpointer data));
+gpointer attrib_def_copy(gpointer attrdef);
+GSList* gslist_deep_copy(GSList* list, COPYFUNC copy_func);
+void gslist_free(GSList** list, void (*elem_free) (gpointer data));
GHashTable* hash_table_new(void);
GHashTable * hash_table_copy(GHashTable* hash);
+void hash_table_dump(GHashTable* hash, FILE* f);
void hash_table_free(GHashTable** hash_table);
void hash_table_keys_to_slist(gpointer key, gpointer value, gpointer slist);
static void parse_attribute(GHashTable* person, xmlDocPtr doc, xmlAttr* attribs) {
xmlChar *str;
- gchar *attr, *value;
+ gchar *attr;
+ AttribDef* data;
while (person && attribs) {
if (g_hash_table_lookup(person, "uid") == NULL ||
- strcasecmp("uid", (const gchar *) attribs->name) != 0) {
+ strcasecmp("uid", (const gchar *) attribs->name) != 0) {
str = xmlNodeListGetString(doc, attribs->children, 1);
attr = (const gchar *) attribs->name;
- value = (const gchar *) str;
- debug_print("\tAttribute: %s->%s\n", attr, value);
- g_hash_table_replace(person, g_strdup(attr), g_strdup(value));
+ debug_print("\tAttribute: %s->%s\n", attr, (const gchar *) str);
+ data = pack_data(ATTRIB_TYPE_STRING, attr, (const gchar *) str);
+ g_hash_table_replace(person, g_strdup(attr), data);
xmlFree(str);
}
attribs = attribs->next;
xmlAttr* attribs;
xmlChar *xvalue, *xkey;
gchar *key = NULL, *value = NULL;
+ AttribDef* data;
cur = cur->xmlChildrenNode;
while (cur != NULL) {
}
attribs = attribs->next;
}
- debug_print("\tAttribute: %s->%s\n", key, value);
if (person && key && value) {
- g_hash_table_replace(person, key, value);
+ debug_print("\tAttribute: %s->%s\n", key, value);
+ data = pack_data(ATTRIB_TYPE_STRING, key, value);
+ g_hash_table_replace(person, g_strdup(key), data);
}
- else {
- if (key) {
- g_free(key);
- key = NULL;
- }
- if (value) {
- g_free(value);
- value = NULL;
- }
+ if (key) {
+ g_free(key);
+ key = NULL;
+ }
+ if (value) {
+ g_free(value);
+ value = NULL;
}
}
cur = cur->next;
}
static gchar* hash_table_get_entry(GHashTable* hash, const gchar* key) {
- gchar* value;
+ AttribDef* attr;
if (! hash || ! key)
return "";
- value = g_hash_table_lookup(hash, key);
+ attr = g_hash_table_lookup(hash, key);
- return (value) ? value : "";
+ return (attr) ? attr->value.string : "";
}
static void hash_table_get_entries(gpointer key,
gpointer data) {
xmlNodePtr attribute;
xmlNodePtr parent = (xmlNodePtr) data;
- gchar* val = (value) ? value : "";
+ AttribDef* attr = (AttribDef *) value;
const gchar** reserved = RESERVED;
while (key && *reserved) {
return;
}
}
-
+
+ gchar* val = (attr) ? attr->value.string : "";
attribute = xmlNewNode(NULL, (const xmlChar *) "attribute");
xmlSetProp(attribute, (xmlChar *) "name", (xmlChar *) g_strdup(key));
xmlNodeAddContent(attribute, (const xmlChar *) g_strdup(val));
xmlNodePtr cur;
GList* head;
Contact* remove = NULL;
- AttribDef compare;
+ AttribDef* compare;
gchar* value;
int bytes;
xmlThrDefIndentTreeOutput(1);
- compare.type = ATTRIB_TYPE_STRING;
- compare.attrib_name = "uid";
+ compare = g_new0(AttribDef, 1);
+ compare->type = ATTRIB_TYPE_STRING;
+ compare->attrib_name = g_strdup("uid");
for (head = abook->contacts; head; head = g_list_next(head)) {
remove = (Contact *) head->data;
- if (contact_compare_attrib(contact, remove, &compare))
+ if (contact_compare_attrib(contact, remove, compare))
break;
}
- value = (gchar *) g_hash_table_lookup(remove->data, compare.attrib_name);
- cur = cur->xmlChildrenNode;
- while (cur != NULL) {
- if (cur->name && !xmlStrcmp(cur->name, (const xmlChar *) "person")) {
- debug_print("Parsing: %s\n", cur->name);
- if (value && has_attribute(doc, cur, compare.attrib_name, value)) {
- xmlUnlinkNode(cur);
- xmlFreeNode(cur);
- bytes = xmlSaveFormatFileEnc(abook->URL, doc, "UTF-8", 1);
- if (bytes == -1) {
- *error = g_strdup_printf(_("%s: Not saved"), abook->URL);
+ if (debug_get_mode())
+ contact_dump(contact, stderr);
+ value = g_strdup(compare->attrib_name);
+ attrib_def_free(compare);
+
+ compare = g_hash_table_lookup(remove->data, value);
+ g_free(value);
+
+ value = compare->value.string;
+
+ if (value) {
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ if (cur->name && !xmlStrcmp(cur->name, (const xmlChar *) "person")) {
+ debug_print("Parsing: %s\n", cur->name);
+ if (has_attribute(doc, cur, compare->attrib_name, value)) {
+ xmlUnlinkNode(cur);
+ xmlFreeNode(cur);
+ bytes = xmlSaveFormatFileEnc(abook->URL, doc, "UTF-8", 1);
+ if (bytes == -1) {
+ *error = g_strdup_printf(_("%s: Not saved"), abook->URL);
+ }
+ break;
}
- break;
}
+ cur = cur->next;
}
- cur = cur->next;
}
xmlFreeDoc(doc);