#include "addressbook.h"
#include "main.h"
-#define LOG_MESSAGE \
- debug_mode == 0 ? (debug_mode == debug_mode) : (void)debug_print
-
/* How it works:
*
* The address book is read into memory. We set up an address list
if (!name || !address) return -1;
+ debug_print( "completion: add_address: %s - %s\n", name, address );
+
ae = g_new0(address_entry, 1);
ce1 = g_new0(completion_entry, 1),
ce2 = g_new0(completion_entry, 1);
return 0;
}
-static gboolean get_all_addresses(GNode *node, gpointer ae)
-{
- XMLNode *xmlnode = (XMLNode *)node->data;
- address_entry *addr = (address_entry *)ae;
-
- /* this simply checks if tag is "item". in that case, it
- * verifies it has already seen an item. if it did, an
- * address retrieval was complete */
- if (!strcmp(xmlnode->tag->tag, "item")) {
- /* see if a previous item was complete */
- /* TODO: does sylpheed address book allow empty names to be entered?
- * if so, addr->name *AND* addr->address should be checked. */
- /* add address to our database */
- add_address(addr->name, addr->address);
- g_free(addr->name);
- g_free(addr->address);
- addr->name = NULL;
- addr->address = NULL;
- } else if (!strcmp(xmlnode->tag->tag, "name"))
- addr->name = g_strdup(xmlnode->element);
- else if (!strcmp(xmlnode->tag->tag, "address"))
- addr->address = g_strdup(xmlnode->element);
-
- return FALSE;
-}
-
/* read_address_book()
*/
-static void read_address_book(void)
-{
- gchar *path;
- GNode *tree;
- address_entry ad = {NULL, NULL};
-
- LOG_MESSAGE( _("%s%d entering read_address_book\n"), __FILE__, __LINE__);
- path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ADDRESS_BOOK, NULL);
- tree = xml_parse_file(path);
- g_free(path);
- if (!tree) {
- LOG_MESSAGE( _("%s(%d) no addressbook\n"), __FILE__, __LINE__);
- return;
- }
-
- /* retrieve all addresses */
- g_node_traverse(tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) get_all_addresses, &ad);
- /* still one pending? */
- if (ad.name) {
- add_address(ad.name, ad.address);
- if (ad.name)
- g_free(ad.name);
- if (ad.address)
- g_free(ad.address);
- }
-
- xml_free_tree(tree);
-
- LOG_MESSAGE(_("%s(%d) leaving read_address_book - OK\n"), __FILE__, __LINE__);
+static void read_address_book(void) {
+ addressbook_load_completion( add_address );
}
/* start_address_completion() - returns the number of addresses
g_completion_add_items(g_completion, g_completion_list);
}
g_ref_count++;
- LOG_MESSAGE("start_address_completion ref count %d\n", g_ref_count);
+ debug_print("start_address_completion ref count %d\n", g_ref_count);
return g_list_length(g_completion_list);
}
wchar_t *wtext;
wchar_t *wp;
wchar_t rfc_mail_sep;
+ wchar_t quote;
+ wchar_t lt;
+ gboolean in_quote = FALSE;
gchar *str;
+ if (mbtowc(&rfc_mail_sep, ",", 1) < 0) return NULL;
+ if (mbtowc("e, "\"", 1) < 0) return NULL;
+ if (mbtowc(<, "<", 1) < 0) return NULL;
+
edit_text = gtk_entry_get_text(entry);
if (edit_text == NULL) return NULL;
cur_pos = gtk_editable_get_position(GTK_EDITABLE(entry));
- if (mbtowc(&rfc_mail_sep, ",", 1) < 0) {
- g_free(wtext);
- return NULL;
- }
-
/* scan for a separator. doesn't matter if walk points at null byte. */
- for (wp = wtext + cur_pos; wp > wtext && *wp != rfc_mail_sep; wp--)
- ;
+ for (wp = wtext + cur_pos; wp > wtext; wp--) {
+ if (!in_quote && *wp == rfc_mail_sep)
+ break;
+ if (*wp == quote)
+ in_quote ^= TRUE;
+ }
/* have something valid */
if (wcslen(wp) == 0) {
return NULL;
}
-#define IS_VALID_CHAR(x) (iswalnum(x) || ((x) > 0x7f))
+#define IS_VALID_CHAR(x) \
+ (iswalnum(x) || (x) == quote || (x) == lt || ((x) > 0x7f))
/* now scan back until we hit a valid character */
for (; *wp && !IS_VALID_CHAR(*wp); wp++)
gchar *get_complete_address(gint index)
{
const address_entry *p;
-
+ gchar *address = NULL;
+
if (index < g_completion_count) {
if (index == 0)
- return g_strdup(g_completion_prefix);
+ address = g_strdup(g_completion_prefix);
else {
/* get something from the unique addresses */
p = (address_entry *)g_slist_nth_data
(g_completion_addresses, index - 1);
- if (p == NULL)
- return NULL;
- else
- return g_strdup_printf
- ("%s <%s>", p->name, p->address);
+ if (p != NULL) {
+ if (!p->name || p->name[0] == '\0')
+ address = g_strdup_printf(p->address);
+ else if (strchr_with_skip_quote(p->name, '"', ','))
+ address = g_strdup_printf
+ ("\"%s\" <%s>", p->name, p->address);
+ else
+ address = g_strdup_printf
+ ("%s <%s>", p->name, p->address);
+ }
}
- } else
- return NULL;
+ }
+
+ return address;
}
gchar *get_next_complete_address(void)
guint get_completion_count(void)
{
- if (is_completion_pending)
+ if (is_completion_pending())
return g_completion_count;
else
return 0;
{
if (g_ref_count) {
/* simply the same as start_address_completion() */
- LOG_MESSAGE("Invalidation request for address completion\n");
+ debug_print("Invalidation request for address completion\n");
free_all();
init_all();
read_address_book();
if (0 == --g_ref_count)
free_all();
- LOG_MESSAGE("end_address_completion ref count %d\n", g_ref_count);
+ debug_print("end_address_completion ref count %d\n", g_ref_count);
return g_ref_count;
}
mainwindow);
}
+/* Need unique data to make unregistering signal handler possible for the auto
+ * completed entry */
+#define COMPLETION_UNIQUE_DATA (GINT_TO_POINTER(0xfeefaa))
+
void address_completion_register_entry(GtkEntry *entry)
{
g_return_if_fail(entry != NULL);
gtk_signal_connect_full(GTK_OBJECT(entry), "key_press_event",
GTK_SIGNAL_FUNC(address_completion_entry_key_pressed),
NULL,
- NULL,
+ COMPLETION_UNIQUE_DATA,
NULL,
0,
0); /* magic */
}
+void address_completion_unregister_entry(GtkEntry *entry)
+{
+ GtkObject *entry_obj;
+
+ g_return_if_fail(entry != NULL);
+ g_return_if_fail(GTK_IS_ENTRY(entry));
+
+ entry_obj = gtk_object_get_data(GTK_OBJECT(entry), ENTRY_DATA_TAB_HOOK);
+ g_return_if_fail(entry_obj);
+ g_return_if_fail(entry_obj == GTK_OBJECT(entry));
+
+ /* has the hooked property? */
+ gtk_object_set_data(GTK_OBJECT(entry), ENTRY_DATA_TAB_HOOK, NULL);
+
+ /* remove the hook */
+ gtk_signal_disconnect_by_func(GTK_OBJECT(entry),
+ GTK_SIGNAL_FUNC(address_completion_entry_key_pressed),
+ COMPLETION_UNIQUE_DATA);
+}
+
/* should be called when main window with address completion entries
- * terminates */
+ * terminates.
+ * NOTE: this function assumes that it is called upon destruction of
+ * the window */
void address_completion_end(GtkWidget *mainwindow)
{
/* if address_completion_end() is really called on closing the window,