2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001 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 * Functions to maintain address cache.
28 /* #include "mgutils.h" */
30 #include "addrcache.h"
32 #define ID_TIME_OFFSET 998000000
33 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
36 * Create new address cache.
38 AddressCache *addrcache_create() {
42 cache = g_new0( AddressCache, 1 );
43 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
45 cache->dataRead = FALSE;
46 cache->modified = FALSE;
47 cache->modifyTime = 0;
49 /* Generate the next ID using system time */
53 cache->nextID = t - ID_TIME_OFFSET;
56 cache->tempList = NULL;
57 cache->rootFolder = addritem_create_item_folder();
58 cache->rootFolder->isRoot = TRUE;
59 ADDRITEM_PARENT(cache->rootFolder) = NULL;
66 ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
67 g_return_val_if_fail( cache != NULL, NULL );
68 return cache->rootFolder;
70 GList *addrcache_get_list_folder( AddressCache *cache ) {
71 g_return_val_if_fail( cache != NULL, NULL );
72 return cache->rootFolder->listFolder;
74 GList *addrcache_get_list_person( AddressCache *cache ) {
75 g_return_val_if_fail( cache != NULL, NULL );
76 return cache->rootFolder->listPerson;
82 void addrcache_next_id( AddressCache *cache ) {
83 g_return_if_fail( cache != NULL );
88 * Refresh internal variables. This can be used force a reload.
90 void addrcache_refresh( AddressCache *cache ) {
91 cache->dataRead = FALSE;
92 cache->modified = TRUE;
93 cache->modifyTime = 0;
97 * Free hash table visitor function.
99 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
100 AddrItemObject *obj = ( AddrItemObject * ) value;
101 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
102 addritem_free_item_person( ( ItemPerson * ) obj );
104 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
105 addritem_free_item_group( ( ItemGroup * ) obj );
107 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
108 addritem_free_item_folder( ( ItemFolder * ) obj );
116 * Free hash table of address cache items.
118 static void addrcache_free_item_hash( GHashTable *table ) {
119 g_return_if_fail( table != NULL );
120 g_hash_table_freeze( table );
121 g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
122 g_hash_table_thaw( table );
123 g_hash_table_destroy( table );
127 * Free up folders and groups.
129 static void addrcache_free_all_folders( ItemFolder *parent ) {
130 GList *node = parent->listFolder;
132 ItemFolder *folder = node->data;
133 addrcache_free_all_folders( folder );
134 node = g_list_next( node );
136 g_list_free( parent->listPerson );
137 g_list_free( parent->listGroup );
138 g_list_free( parent->listFolder );
139 parent->listPerson = NULL;
140 parent->listGroup = NULL;
141 parent->listFolder = NULL;
145 * Clear the address cache.
147 void addrcache_clear( AddressCache *cache ) {
148 g_return_if_fail( cache != NULL );
150 /* Free up folders and hash table */
151 addrcache_free_all_folders( cache->rootFolder );
152 addrcache_free_item_hash( cache->itemHash );
153 cache->itemHash = NULL;
154 ADDRITEM_PARENT(cache->rootFolder) = NULL;
155 addritem_free_item_folder( cache->rootFolder );
156 cache->rootFolder = NULL;
157 g_list_free( cache->tempList );
158 cache->tempList = NULL;
160 /* Reset to initial state */
161 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
162 cache->rootFolder = addritem_create_item_folder();
163 cache->rootFolder->isRoot = TRUE;
164 ADDRITEM_PARENT(cache->rootFolder) = NULL;
166 addrcache_refresh( cache );
171 * Free address cache.
173 void addrcache_free( AddressCache *cache ) {
174 g_return_if_fail( cache != NULL );
176 addrcache_free_all_folders( cache->rootFolder );
177 addrcache_free_item_hash( cache->itemHash );
178 cache->itemHash = NULL;
179 ADDRITEM_PARENT(cache->rootFolder) = NULL;
180 addritem_free_item_folder( cache->rootFolder );
181 cache->rootFolder = NULL;
182 g_list_free( cache->tempList );
183 cache->tempList = NULL;
188 * Check whether file has changed by comparing with cache.
189 * return: TRUE if file has changed.
191 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
193 struct stat filestat;
196 if( 0 == lstat( path, &filestat ) ) {
197 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
204 * Save file time to cache.
205 * return: TRUE if time marked.
207 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
208 gboolean retVal = FALSE;
209 struct stat filestat;
211 if( 0 == lstat( path, &filestat ) ) {
212 cache->modifyTime = filestat.st_mtime;
220 * Print list of items.
222 void addrcache_print_item_list( GList *list, FILE *stream ) {
225 AddrItemObject *obj = node->data;
226 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
227 addritem_print_item_person( ( ItemPerson * ) obj, stream );
229 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
230 addritem_print_item_group( ( ItemGroup * ) obj, stream );
232 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
233 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
235 node = g_list_next( node );
237 fprintf( stream, "\t---\n" );
241 * Print item hash table visitor function.
243 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
244 AddrItemObject *obj = ( AddrItemObject * ) value;
245 FILE *stream = ( FILE * ) data;
246 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
247 addritem_print_item_person( ( ItemPerson * ) obj, stream );
249 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
250 addritem_print_item_group( ( ItemGroup * ) obj, stream );
252 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
253 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
258 * Dump entire address cache hash table contents.
260 void addrcache_print( AddressCache *cache, FILE *stream ) {
261 g_return_if_fail( cache != NULL );
262 fprintf( stream, "AddressCache:\n" );
263 fprintf( stream, "next id : %d\n", cache->nextID );
264 fprintf( stream, "mod time : %ld\n", cache->modifyTime );
265 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
266 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
270 * Dump entire address cache hash table contents.
272 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
273 g_return_if_fail( cache != NULL );
274 addrcache_print( cache, stream );
275 g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
279 * Allocate ID for person.
281 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
282 g_return_if_fail( cache != NULL );
283 g_return_if_fail( person != NULL );
284 if( ADDRITEM_ID(person) ) return;
285 addrcache_next_id( cache );
286 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
290 * Allocate ID for group.
292 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
293 g_return_if_fail( cache != NULL );
294 g_return_if_fail( group != NULL );
295 if( ADDRITEM_ID(group) ) return;
296 addrcache_next_id( cache );
297 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
301 * Allocate ID for folder.
303 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
304 g_return_if_fail( cache != NULL );
305 g_return_if_fail( folder != NULL );
306 if( ADDRITEM_ID(folder) ) return;
307 addrcache_next_id( cache );
308 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
312 * Allocate ID for email address.
314 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
315 g_return_if_fail( cache != NULL );
316 g_return_if_fail( email != NULL );
317 if( ADDRITEM_ID(email) ) return;
318 addrcache_next_id( cache );
319 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
323 * Allocate ID for user attribute.
325 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
326 g_return_if_fail( cache != NULL );
327 g_return_if_fail( attrib != NULL );
328 if( attrib->uid ) return;
329 addrcache_next_id( cache );
330 attrib->uid = g_strdup_printf( "%d", cache->nextID );
334 * Add person to hash table.
335 * return: TRUE if item added.
337 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
338 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
341 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
346 * Add group to hash table.
347 * return: TRUE if item added.
349 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
350 g_return_val_if_fail( cache != NULL, FALSE );
351 g_return_val_if_fail( group != NULL, FALSE );
353 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
356 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
361 * Add folder to hash table.
362 * return: TRUE if item added.
364 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
365 g_return_val_if_fail( cache != NULL, FALSE );
366 g_return_val_if_fail( folder != NULL, FALSE );
368 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
371 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
376 * Add person to specified folder in cache.
378 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
379 gboolean retVal = FALSE;
381 g_return_val_if_fail( cache != NULL, FALSE );
382 g_return_val_if_fail( folder != NULL, FALSE );
383 g_return_val_if_fail( item != NULL, FALSE );
385 retVal = addrcache_hash_add_person( cache, item );
387 addritem_folder_add_person( folder, item );
393 * Add folder to specified folder in cache.
395 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
396 gboolean retVal = FALSE;
398 g_return_val_if_fail( cache != NULL, FALSE );
399 g_return_val_if_fail( folder != NULL, FALSE );
400 g_return_val_if_fail( item != NULL, FALSE );
402 retVal = addrcache_hash_add_folder( cache, item );
404 addritem_folder_add_folder( folder, item );
410 * Add folder to specified folder in cache.
412 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
413 gboolean retVal = FALSE;
415 g_return_val_if_fail( cache != NULL, FALSE );
416 g_return_val_if_fail( folder != NULL, FALSE );
417 g_return_val_if_fail( item != NULL, FALSE );
419 retVal = addrcache_hash_add_group( cache, item );
421 addritem_folder_add_group( folder, item );
427 * Add person to address cache.
428 * return: TRUE if item added.
430 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
431 gboolean retVal = FALSE;
433 g_return_val_if_fail( cache != NULL, FALSE );
434 g_return_val_if_fail( person != NULL, FALSE );
436 retVal = addrcache_hash_add_person( cache, person );
438 addritem_folder_add_person( cache->rootFolder, person );
444 * Add EMail address to person.
445 * return: TRUE if item added.
447 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
448 g_return_val_if_fail( cache != NULL, FALSE );
449 g_return_val_if_fail( person != NULL, FALSE );
450 g_return_val_if_fail( email != NULL, FALSE );
452 addritem_person_add_email( person, email );
457 * Add group to address cache.
458 * return: TRUE if item added.
460 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
461 gboolean retVal = FALSE;
463 g_return_val_if_fail( cache != NULL, FALSE );
464 g_return_val_if_fail( group != NULL, FALSE );
466 retVal = addrcache_hash_add_group( cache, group );
468 addritem_folder_add_group( cache->rootFolder, group );
474 * Add EMail address to person.
475 * return: TRUE if item added.
477 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
478 g_return_val_if_fail( cache != NULL, FALSE );
479 g_return_val_if_fail( group != NULL, FALSE );
480 g_return_val_if_fail( email != NULL, FALSE );
482 addritem_group_add_email( group, email );
487 * Add folder to address cache.
488 * return: TRUE if item added.
490 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
491 gboolean retVal = FALSE;
493 g_return_val_if_fail( cache != NULL, FALSE );
494 g_return_val_if_fail( folder != NULL, FALSE );
496 retVal = addrcache_hash_add_folder( cache, folder );
498 addritem_folder_add_folder( cache->rootFolder, folder );
504 * Return pointer to object (either person or group) for specified ID.
505 * param: uid Object ID.
506 * return: Object, or NULL if not found.
508 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
509 AddrItemObject *obj = NULL;
512 g_return_val_if_fail( cache != NULL, NULL );
514 if( uid == NULL || *uid == '\0' ) return NULL;
515 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
517 /* Check for matching UID */
518 uidH = ADDRITEM_ID(obj);
520 if( strcmp( uidH, uid ) == 0 ) return obj;
527 * Return pointer for specified object ID.
528 * param: uid Object ID.
529 * return: Person object, or NULL if not found.
531 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
532 ItemPerson *person = NULL;
533 AddrItemObject *obj = addrcache_get_object( cache, uid );
536 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
537 person = ( ItemPerson * ) obj;
544 * Return pointer for specified object ID.
545 * param: uid group ID.
546 * return: Group object, or NULL if not found.
548 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
549 ItemGroup *group = NULL;
550 AddrItemObject *obj = addrcache_get_object( cache, uid );
553 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
554 group = ( ItemGroup * ) obj;
561 * Find email address in address cache.
562 * param: uid Object ID for person.
564 * return: email object for specified object ID and email ID, or NULL if not found.
566 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *uid, const gchar *eid ) {
567 AddrItemObject *objP;
569 if( eid == NULL || *eid == '\0' ) return NULL;
571 objP = addrcache_get_object( cache, uid );
573 if( ADDRITEM_TYPE(objP) == ITEMTYPE_PERSON ) {
574 /* Sequential search through email addresses */
575 ItemPerson *person = ( ItemPerson * ) objP;
576 GList *nodeMail = person->listEMail;
578 AddrItemObject *objE = nodeMail->data;
579 gchar *ide = ADDRITEM_ID(objE);
581 if( strcmp( ide, eid ) == 0 ) {
582 return ( ItemEMail * ) objE;
585 nodeMail = g_list_next( nodeMail );
593 * Remove attribute from person.
594 * param: uid Object ID for person.
596 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
598 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
599 UserAttribute *attrib = NULL;
602 if( aid == NULL || *aid == '\0' ) return NULL;
604 person = addrcache_get_person( cache, uid );
606 attrib = addritem_person_remove_attrib_id( person, aid );
612 * Remove attribute from person.
613 * param: person Person.
614 * attrib Attribute to remove.
615 * return: UserAttribute object. Note that object should still be freed.
617 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
618 UserAttribute *found = NULL;
620 g_return_val_if_fail( cache != NULL, NULL );
622 if( person && attrib ) {
623 found = addritem_person_remove_attribute( person, attrib );
629 * Remove group from address cache for specified ID.
630 * param: uid Object ID.
631 * return: Group, or NULL if not found. Note that object should still be freed.
633 ItemGroup *addrcache_remove_group_id( AddressCache *cache, const gchar *uid ) {
634 AddrItemObject *obj = NULL;
636 g_return_val_if_fail( cache != NULL, NULL );
638 if( uid == NULL || *uid == '\0' ) return NULL;
639 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
641 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
642 ItemGroup *group = ( ItemGroup * ) obj;
643 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
644 if( ! parent ) parent = cache->rootFolder;
645 /* Remove group from parent's list and hash table */
646 parent->listGroup = g_list_remove( parent->listGroup, group );
647 g_hash_table_remove( cache->itemHash, uid );
648 return ( ItemGroup * ) obj;
655 * Remove group from address cache.
656 * param: group Group to remove.
657 * return: Group, or NULL if not found. Note that object should still be freed.
659 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
660 AddrItemObject *obj = NULL;
662 g_return_val_if_fail( cache != NULL, NULL );
665 gchar *uid = ADDRITEM_ID(group);
666 if( uid == NULL || *uid == '\0' ) return NULL;
667 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
669 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
670 if( ! parent ) parent = cache->rootFolder;
672 /* Remove group from parent's list and hash table */
673 parent->listGroup = g_list_remove( parent->listGroup, obj );
674 g_hash_table_remove( cache->itemHash, uid );
682 * Remove person's email address from all groups in folder.
684 static void addrcache_foldergrp_rem_person( ItemFolder *folder, ItemPerson *person ) {
685 GList *nodeGrp = folder->listGroup;
688 ItemGroup *group = nodeGrp->data;
690 /* Remove each email address that belongs to the person from the list */
691 GList *node = person->listEMail;
693 group->listEMail = g_list_remove( group->listEMail, node->data );
694 node = g_list_next( node );
697 nodeGrp = g_list_next( nodeGrp );
702 * Remove person from address cache for specified ID. Note that person still retains
703 * their EMail addresses. Also, links to these email addresses will be severed from
705 * param: uid Object ID.
706 * return: Person, or NULL if not found. Note that object should still be freed.
708 ItemPerson *addrcache_remove_person_id( AddressCache *cache, const gchar *uid ) {
709 AddrItemObject *obj = NULL;
711 g_return_val_if_fail( cache != NULL, NULL );
713 if( uid == NULL || *uid == '\0' ) return NULL;
714 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
716 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
717 /* Remove person's email addresses from all groups where
718 referenced and from hash table. */
719 ItemPerson *person = ( ItemPerson * ) obj;
720 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
721 if( ! parent ) parent = cache->rootFolder;
722 /* Remove emails from groups, remove from parent's list
724 addrcache_foldergrp_rem_person( parent, person );
725 parent->listPerson = g_list_remove( parent->listPerson, person );
726 g_hash_table_remove( cache->itemHash, uid );
734 * Remove specified person from address cache.
735 * param: person Person to remove.
736 * return: Person, or NULL if not found. Note that object should still be freed.
738 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
739 AddrItemObject *obj = NULL;
741 g_return_val_if_fail( cache != NULL, NULL );
744 gchar *uid = ADDRITEM_ID(person);
745 if( uid == NULL || *uid == '\0' ) return NULL;
746 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
748 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
749 /* Remove person's email addresses from all groups where
750 referenced and from hash table. */
751 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
752 if( ! parent ) parent = cache->rootFolder;
753 addrcache_foldergrp_rem_person( parent, person );
754 parent->listPerson = g_list_remove( parent->listPerson, person );
755 g_hash_table_remove( cache->itemHash, uid );
764 * Remove email from group item hash table visitor function.
766 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
767 AddrItemObject *obj = ( AddrItemObject * ) value;
768 ItemEMail *email = ( ItemEMail * ) data;
771 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
772 ItemGroup *group = ( ItemGroup * ) value;
774 /* Remove each email address that belongs to the person from the list */
775 group->listEMail = g_list_remove( group->listEMail, email );
781 * Remove email address in address cache for specified ID.
782 * param: uid Object ID for person.
784 * return: EMail object, or NULL if not found. Note that object should still be freed.
786 ItemEMail *addrcache_person_remove_email_id( AddressCache *cache, const gchar *uid, const gchar *eid ) {
787 ItemEMail *email = NULL;
790 if( eid == NULL || *eid == '\0' ) return NULL;
792 person = addrcache_get_person( cache, uid );
794 email = addritem_person_remove_email_id( person, eid );
796 /* Remove email from all groups. */
797 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
799 /* Remove email from person's address list */
800 if( person->listEMail ) {
801 person->listEMail = g_list_remove( person->listEMail, email );
803 /* Unlink reference to person. */
804 ADDRITEM_PARENT(email) = NULL;
811 * Remove email address in address cache for specified person.
812 * param: person Person.
813 * email EMail to remove.
814 * return: EMail object, or NULL if not found. Note that object should still be freed.
816 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
817 ItemEMail *found = NULL;
819 g_return_val_if_fail( cache != NULL, NULL );
821 if( person && email ) {
822 found = addritem_person_remove_email( person, email );
824 /* Remove email from all groups. */
825 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
827 /* Remove email from person's address list */
828 if( person->listEMail ) {
829 person->listEMail = g_list_remove( person->listEMail, email );
831 /* Unlink reference to person. */
832 ADDRITEM_PARENT(email) = NULL;
839 * Return link list of address items for root level folder. Note that the list contains
840 * references to items and should be g_free() when done. Do *NOT* attempt to use the
841 * addrcache_free_xxx() functions... this will destroy the address cache data!
842 * Return: List of items, or NULL if none.
844 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
847 ItemFolder *f = folder;
849 g_return_val_if_fail( cache != NULL, NULL );
851 if( ! f ) f = cache->rootFolder;
852 node = f->listPerson;
854 list = g_list_append( list, node->data );
855 node = g_list_next( node );
859 list = g_list_append( list, node->data );
860 node = g_list_next( node );
866 * Return link list of persons for specified folder. Note that the list contains
867 * references to items and should be g_free() when done. Do *NOT* attempt to use the
868 * addrcache_free_xxx() functions... this will destroy the address cache data!
869 * Return: List of items, or NULL if none.
871 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
872 ItemFolder *f = folder;
874 g_return_val_if_fail( cache != NULL, NULL );
876 if( ! f ) f = cache->rootFolder;
877 return addritem_folder_get_person_list( f );
881 * Return link list of group items for specified folder. Note that the list contains
882 * references to items and should be g_free() when done. Do *NOT* attempt to use the
883 * addrcache_free_xxx() functions... this will destroy the address cache data!
884 * Return: List of items, or NULL if none.
886 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
887 ItemFolder *f = folder;
889 g_return_val_if_fail( cache != NULL, NULL );
891 if( ! f ) f = cache->rootFolder;
892 return addritem_folder_get_group_list( f );
896 * Return link list of folder items for specified folder. Note that the list contains
897 * references to items and should be g_free() when done. Do *NOT* attempt to used the
898 * addrcache_free_xxx() functions... this will destroy the address cache data!
899 * Return: List of items, or NULL if none.
901 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
904 ItemFolder *f = folder;
906 g_return_val_if_fail( cache != NULL, NULL );
908 if( ! f ) f = cache->rootFolder;
909 node = f->listFolder;
911 list = g_list_append( list, node->data );
912 node = g_list_next( node );
918 * Return link list of address items for root level folder. Note that the list contains
919 * references to items and should be g_free() when done. Do *NOT* attempt to used the
920 * addrcache_free_xxx() functions... this will destroy the address cache data!
921 * Return: List of items, or NULL if none.
923 GList *addrcache_get_address_list( AddressCache *cache ) {
924 g_return_val_if_fail( cache != NULL, NULL );
925 return addrcache_folder_get_address_list( cache, cache->rootFolder );
929 * Return link list of persons for root level folder. Note that the list contains
930 * references to items and should be g_free() when done. Do *NOT* attempt to used the
931 * addrcache_free_xxx() functions... this will destroy the address cache data!
932 * Return: List of items, or NULL if none.
934 GList *addrcache_get_person_list( AddressCache *cache ) {
935 g_return_val_if_fail( cache != NULL, NULL );
936 return addritem_folder_get_person_list( cache->rootFolder );
940 * Return link list of group items in root level folder. Note that the list contains
941 * references to items and should be g_free() when done. Do *NOT* attempt to used the
942 * addrcache_free_xxx() functions... this will destroy the address cache data!
943 * Return: List of items, or NULL if none.
945 GList *addrcache_get_group_list( AddressCache *cache ) {
946 g_return_val_if_fail( cache != NULL, NULL );
947 return cache->rootFolder->listGroup;
951 * Return link list of folder items in root level folder. Note that the list contains
952 * references to items and should be g_free() when done. Do *NOT* attempt to used the
953 * addrcache_free_xxx() functions... this will destroy the address cache data!
954 * Return: List of items, or NULL if none.
956 GList *addrcache_get_folder_list( AddressCache *cache ) {
957 g_return_val_if_fail( cache != NULL, NULL );
958 return cache->rootFolder->listFolder;
962 * Group visitor function.
964 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
965 AddrItemObject *obj = ( AddrItemObject * ) value;
967 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
968 AddressCache *cache = data;
969 ItemGroup *group = ( ItemGroup * ) obj;
970 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
971 GList *node = group->listEMail;
973 ItemEMail *email = ( ItemEMail * ) node->data;
974 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
975 if( ! g_list_find( cache->tempList, group ) ) {
976 cache->tempList = g_list_append( cache->tempList, group );
979 node = g_list_next( node );
985 * Return link list of groups which contain a reference to specified person's email
988 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
991 g_return_val_if_fail( cache != NULL, NULL );
993 cache->tempList = NULL;
994 cache->tempList = g_list_append( cache->tempList, person );
995 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
996 cache->tempList = g_list_remove( cache->tempList, person );
997 list = cache->tempList;
998 cache->tempList = NULL;
1003 * Find root folder for specified folder.
1004 * Enter: folder Folder to search.
1005 * Return: root folder, or NULL if not found.
1007 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1008 ItemFolder *item = folder;
1012 if( item->isRoot ) break;
1013 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1017 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1023 * Get all persons visitor function.
1025 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1026 AddrItemObject *obj = ( AddrItemObject * ) value;
1028 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1029 AddressCache *cache = data;
1030 cache->tempList = g_list_append( cache->tempList, obj );
1035 * Return link list of all persons in address cache. Note that the list contains
1036 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1037 * this will destroy the address cache data!
1038 * Return: List of items, or NULL if none.
1040 GList *addrcache_get_all_persons( AddressCache *cache ) {
1043 g_return_val_if_fail( cache != NULL, NULL );
1045 cache->tempList = NULL;
1046 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1047 list = cache->tempList;
1048 cache->tempList = NULL;
1053 * Get all groups visitor function.
1055 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1056 AddrItemObject *obj = ( AddrItemObject * ) value;
1058 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1059 AddressCache *cache = data;
1060 cache->tempList = g_list_append( cache->tempList, obj );
1065 * Return link list of all groups in address cache. Note that the list contains
1066 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1067 * this will destroy the address cache data!
1068 * Return: List of items, or NULL if none.
1070 GList *addrcache_get_all_groups( AddressCache *cache ) {
1073 g_return_val_if_fail( cache != NULL, NULL );
1075 cache->tempList = NULL;
1076 g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1077 list = cache->tempList;
1078 cache->tempList = NULL;
1083 * Remove folder from cache. Children are re-parented to parent folder.
1084 * param: folder Folder to remove.
1085 * return: Folder, or NULL if not found. Note that object should still be freed.
1087 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1088 AddrItemObject *obj = NULL;
1090 g_return_val_if_fail( cache != NULL, NULL );
1093 gchar *uid = ADDRITEM_ID(folder);
1094 if( uid == NULL || *uid == '\0' ) return NULL;
1095 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1097 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1099 AddrItemObject *aio;
1100 if( ! parent ) parent = cache->rootFolder;
1102 /* Re-parent children in folder */
1103 node = folder->listFolder;
1105 aio = ( AddrItemObject * ) node->data;
1106 parent->listFolder = g_list_append( parent->listFolder, aio );
1107 aio->parent = ADDRITEM_OBJECT(parent);
1108 node = g_list_next( node );
1110 node = folder->listPerson;
1112 aio = ( AddrItemObject * ) node->data;
1113 parent->listPerson = g_list_append( parent->listPerson, aio );
1114 aio->parent = ADDRITEM_OBJECT(parent);
1115 node = g_list_next( node );
1117 node = folder->listGroup;
1119 aio = ( AddrItemObject * ) node->data;
1120 parent->listGroup = g_list_append( parent->listGroup, aio );
1121 aio->parent = ADDRITEM_OBJECT(parent);
1122 node = g_list_next( node );
1125 /* Remove folder from parent's list and hash table */
1126 parent->listFolder = g_list_remove( parent->listFolder, folder );
1127 ADDRITEM_PARENT(folder) = NULL;
1128 g_hash_table_remove( cache->itemHash, uid );
1136 * Remove folder from cache. Children are deleted.
1137 * param: folder Folder to remove.
1138 * return: Folder, or NULL if not found. Note that object should still be freed.
1140 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1141 AddrItemObject *obj = NULL;
1143 g_return_val_if_fail( cache != NULL, NULL );
1146 gchar *uid = ADDRITEM_ID(folder);
1147 if( uid == NULL || *uid == '\0' ) return NULL;
1148 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1150 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1151 if( ! parent ) parent = cache->rootFolder;
1154 while( folder->listGroup ) {
1155 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1156 item = addrcache_remove_group( cache, item );
1158 addritem_free_item_group( item );
1163 while( folder->listPerson ) {
1164 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1165 item = addrcache_remove_person( cache, item );
1167 addritem_free_item_person( item );
1172 /* Recursive deletion of folder */
1173 while( folder->listFolder ) {
1174 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1175 item = addrcache_remove_folder_delete( cache, item );
1177 addritem_free_item_folder( item );
1182 /* Remove folder from parent's list and hash table */
1183 parent->listFolder = g_list_remove( parent->listFolder, folder );
1184 ADDRITEM_PARENT(folder) = NULL;
1185 g_hash_table_remove( cache->itemHash, uid );
1193 * Add person and address data to cache.
1194 * Enter: cache Cache.
1195 * folder Folder where to add person, or NULL for root folder.
1197 * address EMail address.
1199 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1200 * this will destroy the address book data.
1202 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1203 const gchar *address, const gchar *remarks )
1205 ItemPerson *person = NULL;
1206 ItemEMail *email = NULL;
1207 ItemFolder *f = folder;
1209 g_return_val_if_fail( cache != NULL, NULL );
1211 if( ! f ) f = cache->rootFolder;
1213 /* Create person object */
1214 person = addritem_create_item_person();
1215 addritem_person_set_common_name( person, name );
1216 addrcache_id_person( cache, person );
1217 addrcache_folder_add_person( cache, f, person );
1219 /* Create email object */
1220 email = addritem_create_item_email();
1221 addritem_email_set_address( email, address );
1222 addritem_email_set_remarks( email, remarks );
1223 addrcache_id_email( cache, email );
1224 addritem_person_add_email( person, email );