2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2002 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Functions to maintain address cache.
30 #include "addrcache.h"
32 #define ID_TIME_OFFSET 998000000
33 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
35 static int _nextCacheID__ = 0;
38 * Generate next cache ID.
40 static int addrcache_next_cache_id() {
43 if( _nextCacheID__ == 0 ) {
46 retVal = _nextCacheID__;
52 * Create new address cache.
54 AddressCache *addrcache_create() {
58 cache = g_new0( AddressCache, 1 );
59 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
60 cache->cacheID = g_strdup_printf( "%d", addrcache_next_cache_id() );
62 cache->dataRead = FALSE;
63 cache->modified = FALSE;
64 cache->dirtyFlag = FALSE;
66 cache->modifyTime = 0;
68 /* Generate the next ID using system time */
72 cache->nextID = t - ID_TIME_OFFSET;
75 cache->tempList = NULL;
76 cache->rootFolder = addritem_create_item_folder();
77 cache->rootFolder->isRoot = TRUE;
78 ADDRITEM_PARENT(cache->rootFolder) = NULL;
85 ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
86 g_return_val_if_fail( cache != NULL, NULL );
87 return cache->rootFolder;
89 GList *addrcache_get_list_folder( AddressCache *cache ) {
90 g_return_val_if_fail( cache != NULL, NULL );
91 return cache->rootFolder->listFolder;
93 GList *addrcache_get_list_person( AddressCache *cache ) {
94 g_return_val_if_fail( cache != NULL, NULL );
95 return cache->rootFolder->listPerson;
97 gboolean addrcache_get_dirty( AddressCache *cache ) {
98 g_return_val_if_fail( cache != NULL, FALSE );
99 return cache->dirtyFlag;
101 void addrcache_set_dirty( AddressCache *cache, const gboolean value ) {
102 g_return_if_fail( cache != NULL );
103 cache->dirtyFlag = value;
105 gchar *addrcache_get_name( AddressCache *cache ) {
106 g_return_val_if_fail( cache != NULL, NULL );
109 void addrcache_set_name( AddressCache *cache, const gchar *value ) {
110 g_return_if_fail( cache != NULL );
111 cache->name = mgu_replace_string( cache->name, value );
112 g_strstrip( cache->name );
113 cache->dirtyFlag = TRUE;
119 void addrcache_next_id( AddressCache *cache ) {
120 g_return_if_fail( cache != NULL );
125 * Refresh internal variables. This can be used force a reload.
127 void addrcache_refresh( AddressCache *cache ) {
128 cache->dataRead = FALSE;
129 cache->modified = TRUE;
130 cache->modifyTime = 0;
134 * Free hash table visitor function.
136 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
137 AddrItemObject *obj = ( AddrItemObject * ) value;
138 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
139 /* Free person and their email */
140 addritem_free_item_person( ( ItemPerson * ) obj );
142 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
143 addritem_free_item_group( ( ItemGroup * ) obj );
145 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
146 addritem_free_item_folder( ( ItemFolder * ) obj );
154 * Free hash table of address cache items.
156 static void addrcache_free_item_hash( GHashTable *table ) {
157 g_return_if_fail( table != NULL );
158 g_hash_table_freeze( table );
159 g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
160 g_hash_table_thaw( table );
161 g_hash_table_destroy( table );
165 * Free up folders and groups.
167 static void addrcache_free_all_folders( ItemFolder *parent ) {
168 GList *node = parent->listFolder;
170 ItemFolder *folder = node->data;
171 addrcache_free_all_folders( folder );
172 node = g_list_next( node );
174 g_list_free( parent->listPerson );
175 g_list_free( parent->listGroup );
176 g_list_free( parent->listFolder );
177 parent->listPerson = NULL;
178 parent->listGroup = NULL;
179 parent->listFolder = NULL;
183 * Clear the address cache.
185 void addrcache_clear( AddressCache *cache ) {
186 g_return_if_fail( cache != NULL );
188 /* Free up folders and hash table */
189 addrcache_free_all_folders( cache->rootFolder );
190 addrcache_free_item_hash( cache->itemHash );
191 cache->itemHash = NULL;
192 ADDRITEM_PARENT(cache->rootFolder) = NULL;
193 addritem_free_item_folder( cache->rootFolder );
194 cache->rootFolder = NULL;
195 g_list_free( cache->tempList );
196 cache->tempList = NULL;
198 /* Reset to initial state */
199 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
200 cache->rootFolder = addritem_create_item_folder();
201 cache->rootFolder->isRoot = TRUE;
202 ADDRITEM_PARENT(cache->rootFolder) = NULL;
204 addrcache_refresh( cache );
209 * Free address cache.
211 void addrcache_free( AddressCache *cache ) {
212 g_return_if_fail( cache != NULL );
214 cache->dirtyFlag = FALSE;
215 addrcache_free_all_folders( cache->rootFolder );
216 addrcache_free_item_hash( cache->itemHash );
217 cache->itemHash = NULL;
218 ADDRITEM_PARENT(cache->rootFolder) = NULL;
219 addritem_free_item_folder( cache->rootFolder );
220 cache->rootFolder = NULL;
221 g_list_free( cache->tempList );
222 cache->tempList = NULL;
223 g_free( cache->cacheID );
224 cache->cacheID = NULL;
225 g_free( cache->name );
231 * Check whether file has changed by comparing with cache.
232 * return: TRUE if file has changed.
234 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
236 struct stat filestat;
239 if( 0 == lstat( path, &filestat ) ) {
240 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
247 * Save file time to cache.
248 * return: TRUE if time marked.
250 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
251 gboolean retVal = FALSE;
252 struct stat filestat;
254 if( 0 == lstat( path, &filestat ) ) {
255 cache->modifyTime = filestat.st_mtime;
263 * Print list of items.
265 void addrcache_print_item_list( GList *list, FILE *stream ) {
268 AddrItemObject *obj = node->data;
269 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
270 addritem_print_item_person( ( ItemPerson * ) obj, stream );
272 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
273 addritem_print_item_group( ( ItemGroup * ) obj, stream );
275 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
276 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
278 node = g_list_next( node );
280 fprintf( stream, "\t---\n" );
284 * Print item hash table visitor function.
286 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
287 AddrItemObject *obj = ( AddrItemObject * ) value;
288 FILE *stream = ( FILE * ) data;
289 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
290 addritem_print_item_person( ( ItemPerson * ) obj, stream );
292 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
293 printf( "addrcache: print email\n" );
295 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
296 addritem_print_item_group( ( ItemGroup * ) obj, stream );
298 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
299 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
304 * Dump entire address cache hash table contents.
306 void addrcache_print( AddressCache *cache, FILE *stream ) {
307 g_return_if_fail( cache != NULL );
308 fprintf( stream, "AddressCache:\n" );
309 fprintf( stream, "cache id : %s\n", cache->cacheID );
310 fprintf( stream, "next id : %d\n", cache->nextID );
311 fprintf( stream, "name : %s\n", cache->name );
312 fprintf( stream, "mod time : %ld\n", cache->modifyTime );
313 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
314 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
318 * Dump entire address cache hash table contents.
320 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
321 g_return_if_fail( cache != NULL );
322 addrcache_print( cache, stream );
323 g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
327 * Allocate ID for person.
329 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
330 g_return_if_fail( cache != NULL );
331 g_return_if_fail( person != NULL );
332 if( ADDRITEM_ID(person) ) return;
333 addrcache_next_id( cache );
334 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
338 * Allocate ID for group.
340 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
341 g_return_if_fail( cache != NULL );
342 g_return_if_fail( group != NULL );
343 if( ADDRITEM_ID(group) ) return;
344 addrcache_next_id( cache );
345 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
349 * Allocate ID for folder.
351 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
352 g_return_if_fail( cache != NULL );
353 g_return_if_fail( folder != NULL );
354 if( ADDRITEM_ID(folder) ) return;
355 addrcache_next_id( cache );
356 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
360 * Allocate ID for email address.
362 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
363 g_return_if_fail( cache != NULL );
364 g_return_if_fail( email != NULL );
365 if( ADDRITEM_ID(email) ) return;
366 addrcache_next_id( cache );
367 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
371 * Allocate ID for user attribute.
373 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
374 g_return_if_fail( cache != NULL );
375 g_return_if_fail( attrib != NULL );
376 if( attrib->uid ) return;
377 addrcache_next_id( cache );
378 attrib->uid = g_strdup_printf( "%d", cache->nextID );
382 * Add person to hash table.
383 * return: TRUE if item added.
385 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
386 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
389 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
394 * Add email to hash table.
395 * return: TRUE if item added.
397 gboolean addrcache_hash_add_email( AddressCache *cache, ItemEMail *email ) {
398 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(email) ) ) {
401 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(email), email );
406 * Add group to hash table.
407 * return: TRUE if item added.
409 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
410 g_return_val_if_fail( cache != NULL, FALSE );
411 g_return_val_if_fail( group != NULL, FALSE );
413 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
416 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
421 * Add folder to hash table.
422 * return: TRUE if item added.
424 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
425 g_return_val_if_fail( cache != NULL, FALSE );
426 g_return_val_if_fail( folder != NULL, FALSE );
428 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
431 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
436 * Add person to specified folder in cache.
438 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
439 gboolean retVal = FALSE;
441 g_return_val_if_fail( cache != NULL, FALSE );
442 g_return_val_if_fail( folder != NULL, FALSE );
443 g_return_val_if_fail( item != NULL, FALSE );
445 retVal = addrcache_hash_add_person( cache, item );
447 addritem_folder_add_person( folder, item );
448 cache->dirtyFlag = TRUE;
454 * Add folder to specified folder in cache.
456 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
457 gboolean retVal = FALSE;
459 g_return_val_if_fail( cache != NULL, FALSE );
460 g_return_val_if_fail( folder != NULL, FALSE );
461 g_return_val_if_fail( item != NULL, FALSE );
463 retVal = addrcache_hash_add_folder( cache, item );
465 addritem_folder_add_folder( folder, item );
466 cache->dirtyFlag = TRUE;
472 * Add folder to specified folder in cache.
474 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
475 gboolean retVal = FALSE;
477 g_return_val_if_fail( cache != NULL, FALSE );
478 g_return_val_if_fail( folder != NULL, FALSE );
479 g_return_val_if_fail( item != NULL, FALSE );
481 retVal = addrcache_hash_add_group( cache, item );
483 addritem_folder_add_group( folder, item );
484 cache->dirtyFlag = TRUE;
490 * Add person to address cache.
491 * return: TRUE if item added.
493 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
494 gboolean retVal = FALSE;
496 g_return_val_if_fail( cache != NULL, FALSE );
497 g_return_val_if_fail( person != NULL, FALSE );
499 retVal = addrcache_hash_add_person( cache, person );
501 addritem_folder_add_person( cache->rootFolder, person );
502 cache->dirtyFlag = TRUE;
508 * Add EMail address to person.
509 * return: TRUE if item added.
511 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
512 gboolean retVal = FALSE;
514 g_return_val_if_fail( cache != NULL, FALSE );
515 g_return_val_if_fail( person != NULL, FALSE );
516 g_return_val_if_fail( email != NULL, FALSE );
518 retVal = addrcache_hash_add_email( cache, email );
520 addritem_person_add_email( person, email );
521 cache->dirtyFlag = TRUE;
527 * Add group to address cache.
528 * return: TRUE if item added.
530 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
531 gboolean retVal = FALSE;
533 g_return_val_if_fail( cache != NULL, FALSE );
534 g_return_val_if_fail( group != NULL, FALSE );
536 retVal = addrcache_hash_add_group( cache, group );
538 addritem_folder_add_group( cache->rootFolder, group );
539 cache->dirtyFlag = TRUE;
545 * Add EMail address to person.
546 * return: TRUE if item added.
548 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
549 g_return_val_if_fail( cache != NULL, FALSE );
550 g_return_val_if_fail( group != NULL, FALSE );
551 g_return_val_if_fail( email != NULL, FALSE );
553 addritem_group_add_email( group, email );
554 cache->dirtyFlag = TRUE;
559 * Add folder to address cache.
560 * return: TRUE if item added.
562 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
563 gboolean retVal = FALSE;
565 g_return_val_if_fail( cache != NULL, FALSE );
566 g_return_val_if_fail( folder != NULL, FALSE );
568 retVal = addrcache_hash_add_folder( cache, folder );
570 addritem_folder_add_folder( cache->rootFolder, folder );
571 cache->dirtyFlag = TRUE;
577 * Move person to destination folder.
578 * Enter: cache Cache.
579 * person Person to move.
580 * target Target folder.
582 void addrcache_folder_move_person(
583 AddressCache *cache, ItemPerson *person, ItemFolder *target )
587 g_return_if_fail( cache != NULL );
588 g_return_if_fail( person != NULL );
590 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
591 if( ! parent ) parent = cache->rootFolder;
592 parent->listPerson = g_list_remove( parent->listPerson, person );
593 target->listPerson = g_list_append( target->listPerson, person );
594 ADDRITEM_PARENT(person) = ADDRITEM_OBJECT(target);
595 cache->dirtyFlag = TRUE;
599 * Move group to destination folder.
600 * Enter: cache Cache.
601 * group Group to move.
602 * target Target folder.
604 void addrcache_folder_move_group(
605 AddressCache *cache, ItemGroup *group, ItemFolder *target )
609 g_return_if_fail( cache != NULL );
610 g_return_if_fail( group != NULL );
612 parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
613 if( ! parent ) parent = cache->rootFolder;
614 parent->listGroup = g_list_remove( parent->listGroup, group );
615 target->listGroup = g_list_append( target->listGroup, group );
616 ADDRITEM_PARENT(group) = ADDRITEM_OBJECT(target);
617 cache->dirtyFlag = TRUE;
621 * Move folder to destination folder.
622 * Enter: cache Cache.
623 * folder Folder to move.
624 * target Target folder.
626 void addrcache_folder_move_folder(
627 AddressCache *cache, ItemFolder *folder, ItemFolder *target )
631 g_return_if_fail( cache != NULL );
632 g_return_if_fail( folder != NULL );
634 parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
635 if( ! parent ) parent = cache->rootFolder;
636 parent->listFolder = g_list_remove( parent->listFolder, folder );
637 target->listFolder = g_list_append( target->listFolder, folder );
638 ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(target);
639 cache->dirtyFlag = TRUE;
643 * Return pointer to object (either person or group) for specified ID.
644 * param: uid Object ID.
645 * return: Object, or NULL if not found.
647 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
648 AddrItemObject *obj = NULL;
651 g_return_val_if_fail( cache != NULL, NULL );
653 if( uid == NULL || *uid == '\0' ) return NULL;
654 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
656 /* Check for matching UID */
657 uidH = ADDRITEM_ID(obj);
659 if( strcmp( uidH, uid ) == 0 ) return obj;
666 * Return pointer for specified object ID.
667 * param: uid Object ID.
668 * return: Person object, or NULL if not found.
670 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
671 ItemPerson *person = NULL;
672 AddrItemObject *obj = addrcache_get_object( cache, uid );
675 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
676 person = ( ItemPerson * ) obj;
683 * Return pointer for specified object ID.
684 * param: uid group ID.
685 * return: Group object, or NULL if not found.
687 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
688 ItemGroup *group = NULL;
689 AddrItemObject *obj = addrcache_get_object( cache, uid );
692 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
693 group = ( ItemGroup * ) obj;
700 * Find email address in address cache.
701 * param: eid EMail ID.
702 * return: email object for specified object ID and email ID, or NULL if not found.
704 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *eid ) {
705 ItemEMail *email = NULL;
706 AddrItemObject *obj = addrcache_get_object( cache, eid );
709 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
710 email = ( ItemEMail * ) obj;
717 * Remove attribute from person.
718 * param: uid Object ID for person.
720 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
722 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
723 UserAttribute *attrib = NULL;
726 if( aid == NULL || *aid == '\0' ) return NULL;
728 person = addrcache_get_person( cache, uid );
730 attrib = addritem_person_remove_attrib_id( person, aid );
731 cache->dirtyFlag = TRUE;
737 * Remove attribute from person.
738 * param: person Person.
739 * attrib Attribute to remove.
740 * return: UserAttribute object. Note that object should still be freed.
742 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
743 UserAttribute *found = NULL;
745 g_return_val_if_fail( cache != NULL, NULL );
747 if( person && attrib ) {
748 found = addritem_person_remove_attribute( person, attrib );
749 cache->dirtyFlag = TRUE;
755 * Remove group from address cache.
756 * param: group Group to remove.
757 * return: Group, or NULL if not found. Note that object should still be freed.
759 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
760 AddrItemObject *obj = NULL;
762 g_return_val_if_fail( cache != NULL, NULL );
765 gchar *uid = ADDRITEM_ID(group);
766 if( uid == NULL || *uid == '\0' ) return NULL;
767 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
769 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
770 if( ! parent ) parent = cache->rootFolder;
772 /* Remove group from parent's list and hash table */
773 parent->listGroup = g_list_remove( parent->listGroup, obj );
774 g_hash_table_remove( cache->itemHash, uid );
775 cache->dirtyFlag = TRUE;
783 * Remove specified email from address cache. Note that object is only
784 * removed from cache and not parent objects.
785 * param: email EMail to remove.
786 * return: EMail, or NULL if not found. Note that object should still be freed.
788 ItemEMail *addrcache_remove_email( AddressCache *cache, ItemEMail *email ) {
789 AddrItemObject *obj = NULL;
791 g_return_val_if_fail( cache != NULL, NULL );
794 gchar *eid = ADDRITEM_ID(email);
795 if( eid == NULL || *eid == '\0' ) return NULL;
796 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, eid );
798 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
799 /* Remove email addresses from hash table. */
800 g_hash_table_remove( cache->itemHash, eid );
801 cache->dirtyFlag = TRUE;
810 * Hash table visitor function to remove email from group.
812 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
813 AddrItemObject *obj = ( AddrItemObject * ) value;
814 ItemEMail *email = ( ItemEMail * ) data;
816 if( ! email ) return;
817 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
818 ItemGroup *group = ( ItemGroup * ) value;
820 /* Remove each email address that belongs to the person from the list */
821 group->listEMail = g_list_remove( group->listEMail, email );
827 * Remove specified person from address cache.
828 * param: person Person to remove.
829 * return: Person, or NULL if not found. Note that object should still be freed.
831 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
832 AddrItemObject *obj = NULL;
835 g_return_val_if_fail( cache != NULL, NULL );
838 uid = ADDRITEM_ID(person);
839 if( uid == NULL || *uid == '\0' ) return NULL;
840 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
842 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
846 /* Remove all email addresses for person */
847 /* from groups and from hash table */
848 node = person->listEMail;
854 g_hash_table_foreach( cache->itemHash,
855 addrcache_allgrp_rem_email_vis, email );
856 eid = ADDRITEM_ID( email );
857 g_hash_table_remove( cache->itemHash, eid );
858 node = g_list_next( node );
861 /* Remove person from owning folder */
862 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
863 if( ! parent ) parent = cache->rootFolder;
864 parent->listPerson = g_list_remove( parent->listPerson, person );
865 g_hash_table_remove( cache->itemHash, uid );
866 cache->dirtyFlag = TRUE;
875 * Remove email address in address cache for specified person.
876 * param: person Person.
877 * email EMail to remove.
878 * return: EMail object, or NULL if not found. Note that object should still be freed.
880 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
881 ItemEMail *found = NULL;
883 g_return_val_if_fail( cache != NULL, NULL );
885 if( person && email ) {
886 found = addritem_person_remove_email( person, email );
888 /* Remove email from all groups. */
889 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
891 /* Remove email from person's address list */
892 if( person->listEMail ) {
893 person->listEMail = g_list_remove( person->listEMail, email );
895 /* Unlink reference to person. */
896 ADDRITEM_PARENT(email) = NULL;
897 cache->dirtyFlag = TRUE;
904 * Move email address in address cache to new person. If member of group, address
906 * param: cache Cache.
907 * email EMail to remove.
908 * target Target person.
909 * return: EMail object, or NULL if not found. Note that object should still be freed.
911 void addrcache_person_move_email(
912 AddressCache *cache, ItemEMail *email, ItemPerson *target )
916 g_return_if_fail( cache != NULL );
918 if( email == NULL ) return;
919 if( target == NULL ) return;
921 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
924 found = addritem_person_remove_email( person, email );
926 if( person->listEMail ) {
927 person->listEMail = g_list_remove( person->listEMail, found );
928 addritem_person_add_email( target, found );
929 cache->dirtyFlag = TRUE;
936 * Return link list of address items for root level folder. Note that the list contains
937 * references to items and should be g_free() when done. Do *NOT* attempt to use the
938 * addrcache_free_xxx() functions... this will destroy the address cache data!
939 * Return: List of items, or NULL if none.
941 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
944 ItemFolder *f = folder;
946 g_return_val_if_fail( cache != NULL, NULL );
948 if( ! f ) f = cache->rootFolder;
949 node = f->listPerson;
951 list = g_list_append( list, node->data );
952 node = g_list_next( node );
956 list = g_list_append( list, node->data );
957 node = g_list_next( node );
963 * Return link list of persons for specified folder. Note that the list contains
964 * references to items and should be g_free() when done. Do *NOT* attempt to use the
965 * addrcache_free_xxx() functions... this will destroy the address cache data!
966 * Return: List of items, or NULL if none.
968 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
969 ItemFolder *f = folder;
971 g_return_val_if_fail( cache != NULL, NULL );
973 if( ! f ) f = cache->rootFolder;
974 return addritem_folder_get_person_list( f );
978 * Return link list of group items for specified folder. Note that the list contains
979 * references to items and should be g_free() when done. Do *NOT* attempt to use the
980 * addrcache_free_xxx() functions... this will destroy the address cache data!
981 * Return: List of items, or NULL if none.
983 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
984 ItemFolder *f = folder;
986 g_return_val_if_fail( cache != NULL, NULL );
988 if( ! f ) f = cache->rootFolder;
989 return addritem_folder_get_group_list( f );
993 * Return link list of folder items for specified folder. Note that the list contains
994 * references to items and should be g_free() when done. Do *NOT* attempt to used the
995 * addrcache_free_xxx() functions... this will destroy the address cache data!
996 * Return: List of items, or NULL if none.
998 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
1001 ItemFolder *f = folder;
1003 g_return_val_if_fail( cache != NULL, NULL );
1005 if( ! f ) f = cache->rootFolder;
1006 node = f->listFolder;
1008 list = g_list_append( list, node->data );
1009 node = g_list_next( node );
1015 * Return link list of address items for root level folder. Note that the list contains
1016 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1017 * addrcache_free_xxx() functions... this will destroy the address cache data!
1018 * Return: List of items, or NULL if none.
1020 GList *addrcache_get_address_list( AddressCache *cache ) {
1021 g_return_val_if_fail( cache != NULL, NULL );
1022 return addrcache_folder_get_address_list( cache, cache->rootFolder );
1026 * Return link list of persons for root level folder. Note that the list contains
1027 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1028 * addrcache_free_xxx() functions... this will destroy the address cache data!
1029 * Return: List of items, or NULL if none.
1031 GList *addrcache_get_person_list( AddressCache *cache ) {
1032 g_return_val_if_fail( cache != NULL, NULL );
1033 return addritem_folder_get_person_list( cache->rootFolder );
1037 * Return link list of group items in root level folder. Note that the list contains
1038 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1039 * addrcache_free_xxx() functions... this will destroy the address cache data!
1040 * Return: List of items, or NULL if none.
1042 GList *addrcache_get_group_list( AddressCache *cache ) {
1043 g_return_val_if_fail( cache != NULL, NULL );
1044 return cache->rootFolder->listGroup;
1048 * Return link list of folder items in root level folder. Note that the list contains
1049 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1050 * addrcache_free_xxx() functions... this will destroy the address cache data!
1051 * Return: List of items, or NULL if none.
1053 GList *addrcache_get_folder_list( AddressCache *cache ) {
1054 g_return_val_if_fail( cache != NULL, NULL );
1055 return cache->rootFolder->listFolder;
1059 * Group visitor function.
1061 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
1062 AddrItemObject *obj = ( AddrItemObject * ) value;
1064 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1065 AddressCache *cache = data;
1066 ItemGroup *group = ( ItemGroup * ) obj;
1067 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
1068 GList *node = group->listEMail;
1070 ItemEMail *email = ( ItemEMail * ) node->data;
1071 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
1072 if( ! g_list_find( cache->tempList, group ) ) {
1073 cache->tempList = g_list_append( cache->tempList, group );
1076 node = g_list_next( node );
1082 * Return linked list of groups which contain a reference to specified person's email
1085 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
1088 g_return_val_if_fail( cache != NULL, NULL );
1090 cache->tempList = NULL;
1091 cache->tempList = g_list_append( cache->tempList, person );
1092 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
1093 cache->tempList = g_list_remove( cache->tempList, person );
1094 list = cache->tempList;
1095 cache->tempList = NULL;
1100 * Find root folder for specified folder.
1101 * Enter: folder Folder to search.
1102 * Return: root folder, or NULL if not found.
1104 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1105 ItemFolder *item = folder;
1109 if( item->isRoot ) break;
1110 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1114 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1120 * Get all person visitor function.
1122 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1123 AddrItemObject *obj = ( AddrItemObject * ) value;
1125 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1126 AddressCache *cache = data;
1127 cache->tempList = g_list_append( cache->tempList, obj );
1132 * Return link list of all persons in address cache. Note that the list contains
1133 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1134 * this will destroy the address cache data!
1135 * Return: List of items, or NULL if none.
1137 GList *addrcache_get_all_persons( AddressCache *cache ) {
1140 g_return_val_if_fail( cache != NULL, NULL );
1142 cache->tempList = NULL;
1143 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1144 list = cache->tempList;
1145 cache->tempList = NULL;
1150 * Get all groups visitor function.
1152 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1153 AddrItemObject *obj = ( AddrItemObject * ) value;
1155 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1156 AddressCache *cache = data;
1157 cache->tempList = g_list_append( cache->tempList, obj );
1162 * Return link list of all groups in address cache. Note that the list contains
1163 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1164 * this will destroy the address cache data!
1165 * Return: List of items, or NULL if none.
1167 GList *addrcache_get_all_groups( AddressCache *cache ) {
1170 g_return_val_if_fail( cache != NULL, NULL );
1172 cache->tempList = NULL;
1173 g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1174 list = cache->tempList;
1175 cache->tempList = NULL;
1180 * Remove folder from cache. Children are re-parented to parent folder.
1181 * param: folder Folder to remove.
1182 * return: Folder, or NULL if not found. Note that object should still be freed.
1184 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1185 AddrItemObject *obj = NULL;
1187 g_return_val_if_fail( cache != NULL, NULL );
1190 gchar *uid = ADDRITEM_ID(folder);
1191 if( uid == NULL || *uid == '\0' ) return NULL;
1192 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1194 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1196 AddrItemObject *aio;
1197 if( ! parent ) parent = cache->rootFolder;
1199 /* Re-parent children in folder */
1200 node = folder->listFolder;
1202 aio = ( AddrItemObject * ) node->data;
1203 parent->listFolder = g_list_append( parent->listFolder, aio );
1204 aio->parent = ADDRITEM_OBJECT(parent);
1205 node = g_list_next( node );
1207 node = folder->listPerson;
1209 aio = ( AddrItemObject * ) node->data;
1210 parent->listPerson = g_list_append( parent->listPerson, aio );
1211 aio->parent = ADDRITEM_OBJECT(parent);
1212 node = g_list_next( node );
1214 node = folder->listGroup;
1216 aio = ( AddrItemObject * ) node->data;
1217 parent->listGroup = g_list_append( parent->listGroup, aio );
1218 aio->parent = ADDRITEM_OBJECT(parent);
1219 node = g_list_next( node );
1222 /* Remove folder from parent's list and hash table */
1223 parent->listFolder = g_list_remove( parent->listFolder, folder );
1224 ADDRITEM_PARENT(folder) = NULL;
1225 g_hash_table_remove( cache->itemHash, uid );
1226 cache->dirtyFlag = TRUE;
1234 * Remove folder from cache. Children are deleted.
1235 * param: folder Folder to remove.
1236 * return: Folder, or NULL if not found. Note that object should still be freed.
1238 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1239 AddrItemObject *obj = NULL;
1241 g_return_val_if_fail( cache != NULL, NULL );
1244 gchar *uid = ADDRITEM_ID(folder);
1245 if( uid == NULL || *uid == '\0' ) return NULL;
1246 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1248 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1249 if( ! parent ) parent = cache->rootFolder;
1252 while( folder->listGroup ) {
1253 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1254 item = addrcache_remove_group( cache, item );
1256 addritem_free_item_group( item );
1261 while( folder->listPerson ) {
1262 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1263 item = addrcache_remove_person( cache, item );
1265 addritem_free_item_person( item );
1270 /* Recursive deletion of folder */
1271 while( folder->listFolder ) {
1272 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1273 item = addrcache_remove_folder_delete( cache, item );
1275 addritem_free_item_folder( item );
1280 /* Remove folder from parent's list and hash table */
1281 parent->listFolder = g_list_remove( parent->listFolder, folder );
1282 ADDRITEM_PARENT(folder) = NULL;
1283 g_hash_table_remove( cache->itemHash, uid );
1284 cache->dirtyFlag = TRUE;
1292 * Add person and address data to cache.
1293 * Enter: cache Cache.
1294 * folder Folder where to add person, or NULL for root folder.
1296 * address EMail address.
1298 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1299 * this will destroy the address book data.
1301 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1302 const gchar *address, const gchar *remarks )
1304 ItemPerson *person = NULL;
1305 ItemEMail *email = NULL;
1306 ItemFolder *f = folder;
1308 g_return_val_if_fail( cache != NULL, NULL );
1310 if( ! f ) f = cache->rootFolder;
1312 /* Create person object */
1313 person = addritem_create_item_person();
1314 addritem_person_set_common_name( person, name );
1315 addrcache_id_person( cache, person );
1316 addrcache_folder_add_person( cache, f, person );
1318 /* Create email object */
1319 email = addritem_create_item_email();
1320 addritem_email_set_address( email, address );
1321 addritem_email_set_remarks( email, remarks );
1322 addrcache_id_email( cache, email );
1323 addritem_person_add_email( person, email );
1324 cache->dirtyFlag = TRUE;