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;
65 cache->accessFlag = FALSE;
67 cache->modifyTime = 0;
69 /* Generate the next ID using system time */
73 cache->nextID = t - ID_TIME_OFFSET;
76 cache->tempList = NULL;
77 cache->rootFolder = addritem_create_item_folder();
78 cache->rootFolder->isRoot = TRUE;
79 ADDRITEM_PARENT(cache->rootFolder) = NULL;
86 ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
87 g_return_val_if_fail( cache != NULL, NULL );
88 return cache->rootFolder;
90 GList *addrcache_get_list_folder( AddressCache *cache ) {
91 g_return_val_if_fail( cache != NULL, NULL );
92 return cache->rootFolder->listFolder;
94 GList *addrcache_get_list_person( AddressCache *cache ) {
95 g_return_val_if_fail( cache != NULL, NULL );
96 return cache->rootFolder->listPerson;
98 gboolean addrcache_get_dirty( AddressCache *cache ) {
99 g_return_val_if_fail( cache != NULL, FALSE );
100 return cache->dirtyFlag;
102 void addrcache_set_dirty( AddressCache *cache, const gboolean value ) {
103 g_return_if_fail( cache != NULL );
104 cache->dirtyFlag = value;
106 gboolean addrcache_get_modified( AddressCache *cache ) {
107 g_return_val_if_fail( cache != NULL, FALSE );
108 return cache->modified;
110 void addrcache_set_modified( AddressCache *cache, const gboolean value ) {
111 g_return_if_fail( cache != NULL );
112 cache->modified = value;
114 gboolean addrcache_get_read_flag( AddressCache *cache ) {
115 g_return_val_if_fail( cache != NULL, FALSE );
116 return cache->dataRead;
118 void addrcache_set_read_flag( AddressCache *cache, const gboolean value ) {
119 g_return_if_fail( cache != NULL );
120 cache->dataRead = value;
122 gboolean addrcache_get_accessed( AddressCache *cache ) {
123 g_return_val_if_fail( cache != NULL, FALSE );
124 return cache->accessFlag;
126 void addrcache_set_accessed( AddressCache *cache, const gboolean value ) {
127 g_return_if_fail( cache != NULL );
128 cache->accessFlag = value;
130 gchar *addrcache_get_name( AddressCache *cache ) {
131 g_return_val_if_fail( cache != NULL, NULL );
134 void addrcache_set_name( AddressCache *cache, const gchar *value ) {
135 g_return_if_fail( cache != NULL );
136 cache->name = mgu_replace_string( cache->name, value );
137 g_strstrip( cache->name );
138 cache->dirtyFlag = TRUE;
144 void addrcache_next_id( AddressCache *cache ) {
145 g_return_if_fail( cache != NULL );
150 * Refresh internal variables. This can be used force a reload.
152 void addrcache_refresh( AddressCache *cache ) {
153 cache->dataRead = FALSE;
154 cache->modified = TRUE;
155 cache->accessFlag = FALSE;
156 cache->modifyTime = 0;
160 * Free hash table visitor function.
162 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
163 AddrItemObject *obj = ( AddrItemObject * ) value;
165 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
166 addritem_free_item_person( ( ItemPerson * ) obj );
168 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
169 addritem_free_item_email( ( ItemEMail * ) obj );
171 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
172 addritem_free_item_group( ( ItemGroup * ) obj );
174 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
175 addritem_free_item_folder( ( ItemFolder * ) obj );
183 * Free hash table of address cache items.
185 static void addrcache_free_item_hash( GHashTable *table ) {
186 g_return_if_fail( table != NULL );
187 g_hash_table_freeze( table );
188 g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
189 g_hash_table_thaw( table );
193 * Free up folders and groups.
195 static void addrcache_free_all_folders( ItemFolder *parent ) {
198 if( parent == NULL ) return;
200 node = parent->listFolder;
202 ItemFolder *folder = node->data;
203 addrcache_free_all_folders( folder );
205 node = g_list_next( node );
207 g_list_free( parent->listPerson );
208 g_list_free( parent->listGroup );
209 g_list_free( parent->listFolder );
210 parent->listPerson = NULL;
211 parent->listGroup = NULL;
212 parent->listFolder = NULL;
216 * Clear the address cache.
218 void addrcache_clear( AddressCache *cache ) {
219 g_return_if_fail( cache != NULL );
221 /* printf( "...addrcache_clear :%s:\n", cache->name ); */
222 /* Free up folders and hash table */
223 addrcache_free_all_folders( cache->rootFolder );
224 addrcache_free_item_hash( cache->itemHash );
225 g_hash_table_destroy( cache->itemHash );
226 cache->itemHash = NULL;
227 ADDRITEM_PARENT(cache->rootFolder) = NULL;
228 addritem_free_item_folder( cache->rootFolder );
229 cache->rootFolder = NULL;
230 if( cache->tempList ) g_list_free( cache->tempList );
231 cache->tempList = NULL;
233 /* Reset to initial state */
234 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
235 cache->rootFolder = addritem_create_item_folder();
236 cache->rootFolder->isRoot = TRUE;
237 ADDRITEM_PARENT(cache->rootFolder) = NULL;
239 addrcache_refresh( cache );
243 * Free address cache.
245 void addrcache_free( AddressCache *cache ) {
246 g_return_if_fail( cache != NULL );
248 cache->dirtyFlag = FALSE;
249 addrcache_free_all_folders( cache->rootFolder );
250 addrcache_free_item_hash( cache->itemHash );
251 g_hash_table_destroy( cache->itemHash );
252 cache->itemHash = NULL;
253 ADDRITEM_PARENT(cache->rootFolder) = NULL;
254 addritem_free_item_folder( cache->rootFolder );
255 cache->rootFolder = NULL;
256 g_list_free( cache->tempList );
257 cache->tempList = NULL;
258 g_free( cache->cacheID );
259 cache->cacheID = NULL;
260 g_free( cache->name );
266 * Check whether file has changed by comparing with cache.
267 * return: TRUE if file has changed.
269 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
271 struct stat filestat;
274 if( 0 == lstat( path, &filestat ) ) {
275 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
282 * Save file time to cache.
283 * return: TRUE if time marked.
285 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
286 gboolean retVal = FALSE;
287 struct stat filestat;
289 if( 0 == lstat( path, &filestat ) ) {
290 cache->modifyTime = filestat.st_mtime;
298 * Print list of items.
300 void addrcache_print_item_list( GList *list, FILE *stream ) {
303 AddrItemObject *obj = node->data;
304 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
305 addritem_print_item_person( ( ItemPerson * ) obj, stream );
307 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
308 addritem_print_item_group( ( ItemGroup * ) obj, stream );
310 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
311 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
313 node = g_list_next( node );
315 fprintf( stream, "\t---\n" );
319 * Print item hash table visitor function.
321 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
322 AddrItemObject *obj = ( AddrItemObject * ) value;
323 FILE *stream = ( FILE * ) data;
324 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
325 addritem_print_item_person( ( ItemPerson * ) obj, stream );
327 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
328 printf( "addrcache: print email\n" );
330 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
331 addritem_print_item_group( ( ItemGroup * ) obj, stream );
333 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
334 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
339 * Dump entire address cache hash table contents.
341 void addrcache_print( AddressCache *cache, FILE *stream ) {
342 g_return_if_fail( cache != NULL );
343 fprintf( stream, "AddressCache:\n" );
344 fprintf( stream, "cache id : %s\n", cache->cacheID );
345 fprintf( stream, "next id : %d\n", cache->nextID );
346 fprintf( stream, "name : %s\n", cache->name );
347 fprintf( stream, "mod time : %ld\n", cache->modifyTime );
348 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
349 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
353 * Dump entire address cache hash table contents.
355 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
356 g_return_if_fail( cache != NULL );
357 addrcache_print( cache, stream );
358 g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
362 * Allocate ID for person.
364 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
365 g_return_if_fail( cache != NULL );
366 g_return_if_fail( person != NULL );
367 if( ADDRITEM_ID(person) ) return;
368 addrcache_next_id( cache );
369 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
373 * Allocate ID for group.
375 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
376 g_return_if_fail( cache != NULL );
377 g_return_if_fail( group != NULL );
378 if( ADDRITEM_ID(group) ) return;
379 addrcache_next_id( cache );
380 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
384 * Allocate ID for folder.
386 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
387 g_return_if_fail( cache != NULL );
388 g_return_if_fail( folder != NULL );
389 if( ADDRITEM_ID(folder) ) return;
390 addrcache_next_id( cache );
391 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
395 * Allocate ID for email address.
397 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
398 g_return_if_fail( cache != NULL );
399 g_return_if_fail( email != NULL );
400 if( ADDRITEM_ID(email) ) return;
401 addrcache_next_id( cache );
402 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
406 * Allocate ID for user attribute.
408 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
409 g_return_if_fail( cache != NULL );
410 g_return_if_fail( attrib != NULL );
411 if( attrib->uid ) return;
412 addrcache_next_id( cache );
413 attrib->uid = g_strdup_printf( "%d", cache->nextID );
417 * Add person to hash table.
418 * return: TRUE if item added.
420 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
421 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
424 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
429 * Add email to hash table.
430 * return: TRUE if item added.
432 gboolean addrcache_hash_add_email( AddressCache *cache, ItemEMail *email ) {
433 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(email) ) ) {
436 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(email), email );
441 * Add group to hash table.
442 * return: TRUE if item added.
444 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
445 g_return_val_if_fail( cache != NULL, FALSE );
446 g_return_val_if_fail( group != NULL, FALSE );
448 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
451 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
456 * Add folder to hash table.
457 * return: TRUE if item added.
459 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
460 g_return_val_if_fail( cache != NULL, FALSE );
461 g_return_val_if_fail( folder != NULL, FALSE );
463 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
466 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
471 * Add person to specified folder in cache.
473 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
474 gboolean retVal = FALSE;
476 g_return_val_if_fail( cache != NULL, FALSE );
477 g_return_val_if_fail( folder != NULL, FALSE );
478 g_return_val_if_fail( item != NULL, FALSE );
480 retVal = addrcache_hash_add_person( cache, item );
482 addritem_folder_add_person( folder, item );
483 cache->dirtyFlag = TRUE;
489 * Add folder to specified folder in cache.
491 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
492 gboolean retVal = FALSE;
494 g_return_val_if_fail( cache != NULL, FALSE );
495 g_return_val_if_fail( folder != NULL, FALSE );
496 g_return_val_if_fail( item != NULL, FALSE );
498 retVal = addrcache_hash_add_folder( cache, item );
500 addritem_folder_add_folder( folder, item );
501 cache->dirtyFlag = TRUE;
507 * Add folder to specified folder in cache.
509 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
510 gboolean retVal = FALSE;
512 g_return_val_if_fail( cache != NULL, FALSE );
513 g_return_val_if_fail( folder != NULL, FALSE );
514 g_return_val_if_fail( item != NULL, FALSE );
516 retVal = addrcache_hash_add_group( cache, item );
518 addritem_folder_add_group( folder, item );
519 cache->dirtyFlag = TRUE;
525 * Add person to address cache.
526 * return: TRUE if item added.
528 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
529 gboolean retVal = FALSE;
531 g_return_val_if_fail( cache != NULL, FALSE );
532 g_return_val_if_fail( person != NULL, FALSE );
534 retVal = addrcache_hash_add_person( cache, person );
536 addritem_folder_add_person( cache->rootFolder, person );
537 cache->dirtyFlag = TRUE;
543 * Add EMail address to person.
544 * return: TRUE if item added.
546 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
547 gboolean retVal = FALSE;
549 g_return_val_if_fail( cache != NULL, FALSE );
550 g_return_val_if_fail( person != NULL, FALSE );
551 g_return_val_if_fail( email != NULL, FALSE );
553 retVal = addrcache_hash_add_email( cache, email );
555 addritem_person_add_email( person, email );
556 cache->dirtyFlag = TRUE;
562 * Add group to address cache.
563 * return: TRUE if item added.
565 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
566 gboolean retVal = FALSE;
568 g_return_val_if_fail( cache != NULL, FALSE );
569 g_return_val_if_fail( group != NULL, FALSE );
571 retVal = addrcache_hash_add_group( cache, group );
573 addritem_folder_add_group( cache->rootFolder, group );
574 cache->dirtyFlag = TRUE;
580 * Add EMail address to person.
581 * return: TRUE if item added.
583 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
584 g_return_val_if_fail( cache != NULL, FALSE );
585 g_return_val_if_fail( group != NULL, FALSE );
586 g_return_val_if_fail( email != NULL, FALSE );
588 addritem_group_add_email( group, email );
589 cache->dirtyFlag = TRUE;
594 * Add folder to address cache.
595 * return: TRUE if item added.
597 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
598 gboolean retVal = FALSE;
600 g_return_val_if_fail( cache != NULL, FALSE );
601 g_return_val_if_fail( folder != NULL, FALSE );
603 retVal = addrcache_hash_add_folder( cache, folder );
605 addritem_folder_add_folder( cache->rootFolder, folder );
606 cache->dirtyFlag = TRUE;
612 * Move person to destination folder.
613 * Enter: cache Cache.
614 * person Person to move.
615 * target Target folder.
617 void addrcache_folder_move_person(
618 AddressCache *cache, ItemPerson *person, ItemFolder *target )
622 g_return_if_fail( cache != NULL );
623 g_return_if_fail( person != NULL );
625 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
626 if( ! parent ) parent = cache->rootFolder;
627 parent->listPerson = g_list_remove( parent->listPerson, person );
628 target->listPerson = g_list_append( target->listPerson, person );
629 ADDRITEM_PARENT(person) = ADDRITEM_OBJECT(target);
630 cache->dirtyFlag = TRUE;
634 * Move group to destination folder.
635 * Enter: cache Cache.
636 * group Group to move.
637 * target Target folder.
639 void addrcache_folder_move_group(
640 AddressCache *cache, ItemGroup *group, ItemFolder *target )
644 g_return_if_fail( cache != NULL );
645 g_return_if_fail( group != NULL );
647 parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
648 if( ! parent ) parent = cache->rootFolder;
649 parent->listGroup = g_list_remove( parent->listGroup, group );
650 target->listGroup = g_list_append( target->listGroup, group );
651 ADDRITEM_PARENT(group) = ADDRITEM_OBJECT(target);
652 cache->dirtyFlag = TRUE;
656 * Move folder to destination folder.
657 * Enter: cache Cache.
658 * folder Folder to move.
659 * target Target folder.
661 void addrcache_folder_move_folder(
662 AddressCache *cache, ItemFolder *folder, ItemFolder *target )
666 g_return_if_fail( cache != NULL );
667 g_return_if_fail( folder != NULL );
669 parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
670 if( ! parent ) parent = cache->rootFolder;
671 parent->listFolder = g_list_remove( parent->listFolder, folder );
672 target->listFolder = g_list_append( target->listFolder, folder );
673 ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(target);
674 cache->dirtyFlag = TRUE;
678 * Return pointer to object (either person or group) for specified ID.
679 * param: uid Object ID.
680 * return: Object, or NULL if not found.
682 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
683 AddrItemObject *obj = NULL;
686 g_return_val_if_fail( cache != NULL, NULL );
688 if( uid == NULL || *uid == '\0' ) return NULL;
689 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
691 /* Check for matching UID */
692 uidH = ADDRITEM_ID(obj);
694 if( strcmp( uidH, uid ) == 0 ) return obj;
701 * Return pointer for specified object ID.
702 * param: uid Object ID.
703 * return: Person object, or NULL if not found.
705 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
706 ItemPerson *person = NULL;
707 AddrItemObject *obj = addrcache_get_object( cache, uid );
710 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
711 person = ( ItemPerson * ) obj;
718 * Return pointer for specified object ID.
719 * param: uid group ID.
720 * return: Group object, or NULL if not found.
722 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
723 ItemGroup *group = NULL;
724 AddrItemObject *obj = addrcache_get_object( cache, uid );
727 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
728 group = ( ItemGroup * ) obj;
735 * Find email address in address cache.
736 * param: eid EMail ID.
737 * return: email object for specified object ID and email ID, or NULL if not found.
739 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *eid ) {
740 ItemEMail *email = NULL;
741 AddrItemObject *obj = addrcache_get_object( cache, eid );
744 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
745 email = ( ItemEMail * ) obj;
752 * Remove attribute from person.
753 * param: uid Object ID for person.
755 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
757 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
758 UserAttribute *attrib = NULL;
761 if( aid == NULL || *aid == '\0' ) return NULL;
763 person = addrcache_get_person( cache, uid );
765 attrib = addritem_person_remove_attrib_id( person, aid );
766 cache->dirtyFlag = TRUE;
772 * Remove attribute from person.
773 * param: person Person.
774 * attrib Attribute to remove.
775 * return: UserAttribute object. Note that object should still be freed.
777 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
778 UserAttribute *found = NULL;
780 g_return_val_if_fail( cache != NULL, NULL );
782 if( person && attrib ) {
783 found = addritem_person_remove_attribute( person, attrib );
784 cache->dirtyFlag = TRUE;
790 * Remove group from address cache.
791 * param: group Group to remove.
792 * return: Group, or NULL if not found. Note that object should still be freed.
794 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
795 AddrItemObject *obj = NULL;
797 g_return_val_if_fail( cache != NULL, NULL );
800 gchar *uid = ADDRITEM_ID(group);
801 if( uid == NULL || *uid == '\0' ) return NULL;
802 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
804 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
805 if( ! parent ) parent = cache->rootFolder;
807 /* Remove group from parent's list and hash table */
808 parent->listGroup = g_list_remove( parent->listGroup, obj );
809 g_hash_table_remove( cache->itemHash, uid );
810 cache->dirtyFlag = TRUE;
818 * Remove specified email from address cache. Note that object is only
819 * removed from cache and not parent objects.
820 * param: email EMail to remove.
821 * return: EMail, or NULL if not found. Note that object should still be freed.
823 ItemEMail *addrcache_remove_email( AddressCache *cache, ItemEMail *email ) {
824 AddrItemObject *obj = NULL;
826 g_return_val_if_fail( cache != NULL, NULL );
829 gchar *eid = ADDRITEM_ID(email);
830 if( eid == NULL || *eid == '\0' ) return NULL;
831 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, eid );
833 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
834 /* Remove email addresses from hash table. */
835 g_hash_table_remove( cache->itemHash, eid );
836 cache->dirtyFlag = TRUE;
845 * Hash table visitor function to remove email from group.
847 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
848 AddrItemObject *obj = ( AddrItemObject * ) value;
849 ItemEMail *email = ( ItemEMail * ) data;
851 if( ! email ) return;
852 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
853 ItemGroup *group = ( ItemGroup * ) value;
855 /* Remove each email address that belongs to the person from the list */
856 group->listEMail = g_list_remove( group->listEMail, email );
862 * Remove specified person from address cache.
863 * param: person Person to remove.
864 * return: Person, or NULL if not found. Note that object should still be freed.
866 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
867 AddrItemObject *obj = NULL;
870 g_return_val_if_fail( cache != NULL, NULL );
873 uid = ADDRITEM_ID(person);
874 if( uid == NULL || *uid == '\0' ) return NULL;
875 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
877 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
881 /* Remove all email addresses for person */
882 /* from groups and from hash table */
883 node = person->listEMail;
889 g_hash_table_foreach( cache->itemHash,
890 addrcache_allgrp_rem_email_vis, email );
891 eid = ADDRITEM_ID( email );
892 g_hash_table_remove( cache->itemHash, eid );
893 node = g_list_next( node );
896 /* Remove person from owning folder */
897 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
898 if( ! parent ) parent = cache->rootFolder;
899 parent->listPerson = g_list_remove( parent->listPerson, person );
900 g_hash_table_remove( cache->itemHash, uid );
901 cache->dirtyFlag = TRUE;
910 * Remove email address in address cache for specified person.
911 * param: person Person.
912 * email EMail to remove.
913 * return: EMail object, or NULL if not found. Note that object should still be freed.
915 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
916 ItemEMail *found = NULL;
918 g_return_val_if_fail( cache != NULL, NULL );
920 if( person && email ) {
921 found = addritem_person_remove_email( person, email );
923 /* Remove email from all groups. */
924 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
926 /* Remove email from person's address list */
927 if( person->listEMail ) {
928 person->listEMail = g_list_remove( person->listEMail, email );
930 /* Unlink reference to person. */
931 ADDRITEM_PARENT(email) = NULL;
932 cache->dirtyFlag = TRUE;
939 * Move email address in address cache to new person. If member of group, address
941 * param: cache Cache.
942 * email EMail to remove.
943 * target Target person.
944 * return: EMail object, or NULL if not found. Note that object should still be freed.
946 void addrcache_person_move_email(
947 AddressCache *cache, ItemEMail *email, ItemPerson *target )
951 g_return_if_fail( cache != NULL );
953 if( email == NULL ) return;
954 if( target == NULL ) return;
956 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
959 found = addritem_person_remove_email( person, email );
962 if( person->listEMail ) {
963 person->listEMail = g_list_remove( person->listEMail, found );
964 addritem_person_add_email( target, found );
965 cache->dirtyFlag = TRUE;
968 addritem_person_add_email( target, found );
969 cache->dirtyFlag = TRUE;
975 * Return link list of address items for root level folder. Note that the list contains
976 * references to items and should be g_free() when done. Do *NOT* attempt to use the
977 * addrcache_free_xxx() functions... this will destroy the address cache data!
978 * Return: List of items, or NULL if none.
980 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
983 ItemFolder *f = folder;
985 g_return_val_if_fail( cache != NULL, NULL );
987 if( ! f ) f = cache->rootFolder;
988 node = f->listPerson;
990 list = g_list_append( list, node->data );
991 node = g_list_next( node );
995 list = g_list_append( list, node->data );
996 node = g_list_next( node );
1002 * Return link list of persons for specified folder. Note that the list contains
1003 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1004 * addrcache_free_xxx() functions... this will destroy the address cache data!
1005 * Return: List of items, or NULL if none.
1007 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
1008 ItemFolder *f = folder;
1010 g_return_val_if_fail( cache != NULL, NULL );
1012 if( ! f ) f = cache->rootFolder;
1013 return addritem_folder_get_person_list( f );
1017 * Return link list of group items for specified folder. Note that the list contains
1018 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1019 * addrcache_free_xxx() functions... this will destroy the address cache data!
1020 * Return: List of items, or NULL if none.
1022 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
1023 ItemFolder *f = folder;
1025 g_return_val_if_fail( cache != NULL, NULL );
1027 if( ! f ) f = cache->rootFolder;
1028 return addritem_folder_get_group_list( f );
1032 * Return link list of folder items for specified folder. Note that the list contains
1033 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1034 * addrcache_free_xxx() functions... this will destroy the address cache data!
1035 * Return: List of items, or NULL if none.
1037 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
1040 ItemFolder *f = folder;
1042 g_return_val_if_fail( cache != NULL, NULL );
1044 if( ! f ) f = cache->rootFolder;
1045 node = f->listFolder;
1047 list = g_list_append( list, node->data );
1048 node = g_list_next( node );
1054 * Return link list of address items for root level folder. Note that the list contains
1055 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1056 * addrcache_free_xxx() functions... this will destroy the address cache data!
1057 * Return: List of items, or NULL if none.
1059 GList *addrcache_get_address_list( AddressCache *cache ) {
1060 g_return_val_if_fail( cache != NULL, NULL );
1061 return addrcache_folder_get_address_list( cache, cache->rootFolder );
1065 * Return link list of persons for root level folder. Note that the list contains
1066 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1067 * addrcache_free_xxx() functions... this will destroy the address cache data!
1068 * Return: List of items, or NULL if none.
1070 GList *addrcache_get_person_list( AddressCache *cache ) {
1071 g_return_val_if_fail( cache != NULL, NULL );
1072 return addritem_folder_get_person_list( cache->rootFolder );
1076 * Return link list of group items in root level folder. Note that the list contains
1077 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1078 * addrcache_free_xxx() functions... this will destroy the address cache data!
1079 * Return: List of items, or NULL if none.
1081 GList *addrcache_get_group_list( AddressCache *cache ) {
1082 g_return_val_if_fail( cache != NULL, NULL );
1083 return cache->rootFolder->listGroup;
1087 * Return link list of folder items in root level folder. Note that the list contains
1088 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1089 * addrcache_free_xxx() functions... this will destroy the address cache data!
1090 * Return: List of items, or NULL if none.
1092 GList *addrcache_get_folder_list( AddressCache *cache ) {
1093 g_return_val_if_fail( cache != NULL, NULL );
1094 return cache->rootFolder->listFolder;
1098 * Group visitor function.
1100 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
1101 AddrItemObject *obj = ( AddrItemObject * ) value;
1103 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1104 AddressCache *cache = data;
1105 ItemGroup *group = ( ItemGroup * ) obj;
1106 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
1107 GList *node = group->listEMail;
1109 ItemEMail *email = ( ItemEMail * ) node->data;
1110 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
1111 if( ! g_list_find( cache->tempList, group ) ) {
1112 cache->tempList = g_list_append( cache->tempList, group );
1115 node = g_list_next( node );
1121 * Return linked list of groups which contain a reference to specified person's email
1124 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
1127 g_return_val_if_fail( cache != NULL, NULL );
1129 cache->tempList = NULL;
1130 cache->tempList = g_list_append( cache->tempList, person );
1131 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
1132 cache->tempList = g_list_remove( cache->tempList, person );
1133 list = cache->tempList;
1134 cache->tempList = NULL;
1139 * Find root folder for specified folder.
1140 * Enter: folder Folder to search.
1141 * Return: root folder, or NULL if not found.
1143 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1144 ItemFolder *item = folder;
1148 if( item->isRoot ) break;
1149 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1153 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1159 * Get all person visitor function.
1161 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1162 AddrItemObject *obj = ( AddrItemObject * ) value;
1164 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1165 AddressCache *cache = data;
1166 cache->tempList = g_list_append( cache->tempList, obj );
1171 * Return link list of all persons in address cache. Note that the list contains
1172 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1173 * this will destroy the address cache data!
1174 * Return: List of items, or NULL if none.
1176 GList *addrcache_get_all_persons( AddressCache *cache ) {
1179 g_return_val_if_fail( cache != NULL, NULL );
1181 cache->tempList = NULL;
1182 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1183 list = cache->tempList;
1184 cache->tempList = NULL;
1189 * Get all groups visitor function.
1191 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1192 AddrItemObject *obj = ( AddrItemObject * ) value;
1194 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1195 AddressCache *cache = data;
1196 cache->tempList = g_list_append( cache->tempList, obj );
1201 * Return link list of all groups in address cache. Note that the list contains
1202 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1203 * this will destroy the address cache data!
1204 * Return: List of items, or NULL if none.
1206 GList *addrcache_get_all_groups( AddressCache *cache ) {
1209 g_return_val_if_fail( cache != NULL, NULL );
1211 cache->tempList = NULL;
1212 g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1213 list = cache->tempList;
1214 cache->tempList = NULL;
1219 * Remove folder from cache. Children are re-parented to parent folder.
1220 * param: folder Folder to remove.
1221 * return: Folder, or NULL if not found. Note that object should still be freed.
1223 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1224 AddrItemObject *obj = NULL;
1226 g_return_val_if_fail( cache != NULL, NULL );
1229 gchar *uid = ADDRITEM_ID(folder);
1230 if( uid == NULL || *uid == '\0' ) return NULL;
1231 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1233 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1235 AddrItemObject *aio;
1236 if( ! parent ) parent = cache->rootFolder;
1238 /* Re-parent children in folder */
1239 node = folder->listFolder;
1241 aio = ( AddrItemObject * ) node->data;
1242 parent->listFolder = g_list_append( parent->listFolder, aio );
1243 aio->parent = ADDRITEM_OBJECT(parent);
1244 node = g_list_next( node );
1246 node = folder->listPerson;
1248 aio = ( AddrItemObject * ) node->data;
1249 parent->listPerson = g_list_append( parent->listPerson, aio );
1250 aio->parent = ADDRITEM_OBJECT(parent);
1251 node = g_list_next( node );
1253 node = folder->listGroup;
1255 aio = ( AddrItemObject * ) node->data;
1256 parent->listGroup = g_list_append( parent->listGroup, aio );
1257 aio->parent = ADDRITEM_OBJECT(parent);
1258 node = g_list_next( node );
1261 /* Remove folder from parent's list and hash table */
1262 parent->listFolder = g_list_remove( parent->listFolder, folder );
1263 ADDRITEM_PARENT(folder) = NULL;
1264 g_hash_table_remove( cache->itemHash, uid );
1265 cache->dirtyFlag = TRUE;
1273 * Remove folder from cache. Children are deleted.
1274 * param: folder Folder to remove.
1275 * return: Folder, or NULL if not found. Note that object should still be freed.
1277 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1278 AddrItemObject *obj = NULL;
1280 g_return_val_if_fail( cache != NULL, NULL );
1283 gchar *uid = ADDRITEM_ID(folder);
1284 if( uid == NULL || *uid == '\0' ) return NULL;
1285 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1287 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1288 if( ! parent ) parent = cache->rootFolder;
1291 while( folder->listGroup ) {
1292 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1293 item = addrcache_remove_group( cache, item );
1295 addritem_free_item_group( item );
1300 while( folder->listPerson ) {
1301 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1302 item = addrcache_remove_person( cache, item );
1304 addritem_free_item_person( item );
1309 /* Recursive deletion of folder */
1310 while( folder->listFolder ) {
1311 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1312 item = addrcache_remove_folder_delete( cache, item );
1314 addritem_free_item_folder( item );
1319 /* Remove folder from parent's list and hash table */
1320 parent->listFolder = g_list_remove( parent->listFolder, folder );
1321 ADDRITEM_PARENT(folder) = NULL;
1322 g_hash_table_remove( cache->itemHash, uid );
1323 cache->dirtyFlag = TRUE;
1331 * Add person and address data to cache.
1332 * Enter: cache Cache.
1333 * folder Folder where to add person, or NULL for root folder.
1335 * address EMail address.
1337 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1338 * this will destroy the address book data.
1340 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1341 const gchar *address, const gchar *remarks )
1343 ItemPerson *person = NULL;
1344 ItemEMail *email = NULL;
1345 ItemFolder *f = folder;
1347 g_return_val_if_fail( cache != NULL, NULL );
1349 if( ! f ) f = cache->rootFolder;
1351 /* Create person object */
1352 person = addritem_create_item_person();
1353 addritem_person_set_common_name( person, name );
1354 addrcache_id_person( cache, person );
1355 addrcache_folder_add_person( cache, f, person );
1357 /* Create email object */
1358 email = addritem_create_item_email();
1359 addritem_email_set_address( email, address );
1360 addritem_email_set_remarks( email, remarks );
1361 addrcache_id_email( cache, email );
1362 addritem_person_add_email( person, email );
1363 cache->dirtyFlag = TRUE;