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.
29 #include "addrcache.h"
31 #define ID_TIME_OFFSET 998000000
32 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
34 static int _nextCacheID__ = 0;
37 * Generate next cache ID.
39 static int addrcache_next_cache_id() {
42 if( _nextCacheID__ == 0 ) {
45 retVal = _nextCacheID__;
51 * Create new address cache.
53 AddressCache *addrcache_create() {
57 cache = g_new0( AddressCache, 1 );
58 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
59 cache->cacheID = g_strdup_printf( "%d", addrcache_next_cache_id() );
61 cache->dataRead = FALSE;
62 cache->modified = FALSE;
63 cache->dirtyFlag = FALSE;
64 cache->accessFlag = 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 gboolean addrcache_get_modified( AddressCache *cache ) {
106 g_return_val_if_fail( cache != NULL, FALSE );
107 return cache->modified;
109 void addrcache_set_modified( AddressCache *cache, const gboolean value ) {
110 g_return_if_fail( cache != NULL );
111 cache->modified = value;
113 gboolean addrcache_get_read_flag( AddressCache *cache ) {
114 g_return_val_if_fail( cache != NULL, FALSE );
115 return cache->dataRead;
117 void addrcache_set_read_flag( AddressCache *cache, const gboolean value ) {
118 g_return_if_fail( cache != NULL );
119 cache->dataRead = value;
121 gboolean addrcache_get_accessed( AddressCache *cache ) {
122 g_return_val_if_fail( cache != NULL, FALSE );
123 return cache->accessFlag;
125 void addrcache_set_accessed( AddressCache *cache, const gboolean value ) {
126 g_return_if_fail( cache != NULL );
127 cache->accessFlag = value;
129 gchar *addrcache_get_name( AddressCache *cache ) {
130 g_return_val_if_fail( cache != NULL, NULL );
133 void addrcache_set_name( AddressCache *cache, const gchar *value ) {
134 g_return_if_fail( cache != NULL );
135 cache->name = mgu_replace_string( cache->name, value );
136 g_strstrip( cache->name );
137 cache->dirtyFlag = TRUE;
143 void addrcache_next_id( AddressCache *cache ) {
144 g_return_if_fail( cache != NULL );
149 * Refresh internal variables. This can be used force a reload.
151 void addrcache_refresh( AddressCache *cache ) {
152 cache->dataRead = FALSE;
153 cache->modified = TRUE;
154 cache->accessFlag = FALSE;
155 cache->modifyTime = 0;
159 * Free hash table visitor function.
161 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
162 AddrItemObject *obj = ( AddrItemObject * ) value;
163 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
164 /* Free person and their email */
165 addritem_free_item_person( ( ItemPerson * ) obj );
167 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
168 addritem_free_item_group( ( ItemGroup * ) obj );
170 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
171 addritem_free_item_folder( ( ItemFolder * ) obj );
179 * Free hash table of address cache items.
181 static void addrcache_free_item_hash( GHashTable *table ) {
182 g_return_if_fail( table != NULL );
183 g_hash_table_freeze( table );
184 g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
185 g_hash_table_thaw( table );
189 * Free up folders and groups.
191 static void addrcache_free_all_folders( ItemFolder *parent ) {
194 if( parent == NULL ) return;
196 node = parent->listFolder;
198 ItemFolder *folder = node->data;
199 addrcache_free_all_folders( folder );
201 node = g_list_next( node );
203 g_list_free( parent->listPerson );
204 g_list_free( parent->listGroup );
205 g_list_free( parent->listFolder );
206 parent->listPerson = NULL;
207 parent->listGroup = NULL;
208 parent->listFolder = NULL;
212 * Clear the address cache.
214 void addrcache_clear( AddressCache *cache ) {
215 g_return_if_fail( cache != NULL );
217 /* printf( "...addrcache_clear :%s:\n", cache->name ); */
218 /* Free up folders and hash table */
219 addrcache_free_all_folders( cache->rootFolder );
220 addrcache_free_item_hash( cache->itemHash );
221 g_hash_table_destroy( cache->itemHash );
222 cache->itemHash = NULL;
223 ADDRITEM_PARENT(cache->rootFolder) = NULL;
224 addritem_free_item_folder( cache->rootFolder );
225 cache->rootFolder = NULL;
226 if( cache->tempList ) g_list_free( cache->tempList );
227 cache->tempList = NULL;
229 /* Reset to initial state */
230 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
231 cache->rootFolder = addritem_create_item_folder();
232 cache->rootFolder->isRoot = TRUE;
233 ADDRITEM_PARENT(cache->rootFolder) = NULL;
235 addrcache_refresh( cache );
239 * Free address cache.
241 void addrcache_free( AddressCache *cache ) {
242 g_return_if_fail( cache != NULL );
244 cache->dirtyFlag = FALSE;
245 addrcache_free_all_folders( cache->rootFolder );
246 addrcache_free_item_hash( cache->itemHash );
247 g_hash_table_destroy( cache->itemHash );
248 cache->itemHash = NULL;
249 ADDRITEM_PARENT(cache->rootFolder) = NULL;
250 addritem_free_item_folder( cache->rootFolder );
251 cache->rootFolder = NULL;
252 g_list_free( cache->tempList );
253 cache->tempList = NULL;
254 g_free( cache->cacheID );
255 cache->cacheID = NULL;
256 g_free( cache->name );
262 * Check whether file has changed by comparing with cache.
263 * return: TRUE if file has changed.
265 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
267 struct stat filestat;
270 if( 0 == lstat( path, &filestat ) ) {
271 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
278 * Save file time to cache.
279 * return: TRUE if time marked.
281 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
282 gboolean retVal = FALSE;
283 struct stat filestat;
285 if( 0 == lstat( path, &filestat ) ) {
286 cache->modifyTime = filestat.st_mtime;
294 * Print list of items.
296 void addrcache_print_item_list( GList *list, FILE *stream ) {
299 AddrItemObject *obj = node->data;
300 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
301 addritem_print_item_person( ( ItemPerson * ) obj, stream );
303 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
304 addritem_print_item_group( ( ItemGroup * ) obj, stream );
306 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
307 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
309 node = g_list_next( node );
311 fprintf( stream, "\t---\n" );
315 * Print item hash table visitor function.
317 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
318 AddrItemObject *obj = ( AddrItemObject * ) value;
319 FILE *stream = ( FILE * ) data;
320 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
321 addritem_print_item_person( ( ItemPerson * ) obj, stream );
323 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
324 printf( "addrcache: print email\n" );
326 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
327 addritem_print_item_group( ( ItemGroup * ) obj, stream );
329 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
330 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
335 * Dump entire address cache hash table contents.
337 void addrcache_print( AddressCache *cache, FILE *stream ) {
338 g_return_if_fail( cache != NULL );
339 fprintf( stream, "AddressCache:\n" );
340 fprintf( stream, "cache id : %s\n", cache->cacheID );
341 fprintf( stream, "next id : %d\n", cache->nextID );
342 fprintf( stream, "name : %s\n", cache->name );
343 fprintf( stream, "mod time : %ld\n", cache->modifyTime );
344 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
345 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
349 * Dump entire address cache hash table contents.
351 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
352 g_return_if_fail( cache != NULL );
353 addrcache_print( cache, stream );
354 g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
358 * Allocate ID for person.
360 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
361 g_return_if_fail( cache != NULL );
362 g_return_if_fail( person != NULL );
363 if( ADDRITEM_ID(person) ) return;
364 addrcache_next_id( cache );
365 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
369 * Allocate ID for group.
371 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
372 g_return_if_fail( cache != NULL );
373 g_return_if_fail( group != NULL );
374 if( ADDRITEM_ID(group) ) return;
375 addrcache_next_id( cache );
376 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
380 * Allocate ID for folder.
382 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
383 g_return_if_fail( cache != NULL );
384 g_return_if_fail( folder != NULL );
385 if( ADDRITEM_ID(folder) ) return;
386 addrcache_next_id( cache );
387 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
391 * Allocate ID for email address.
393 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
394 g_return_if_fail( cache != NULL );
395 g_return_if_fail( email != NULL );
396 if( ADDRITEM_ID(email) ) return;
397 addrcache_next_id( cache );
398 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
402 * Allocate ID for user attribute.
404 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
405 g_return_if_fail( cache != NULL );
406 g_return_if_fail( attrib != NULL );
407 if( attrib->uid ) return;
408 addrcache_next_id( cache );
409 attrib->uid = g_strdup_printf( "%d", cache->nextID );
413 * Add person to hash table.
414 * return: TRUE if item added.
416 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
417 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
420 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
425 * Add email to hash table.
426 * return: TRUE if item added.
428 gboolean addrcache_hash_add_email( AddressCache *cache, ItemEMail *email ) {
429 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(email) ) ) {
432 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(email), email );
437 * Add group to hash table.
438 * return: TRUE if item added.
440 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
441 g_return_val_if_fail( cache != NULL, FALSE );
442 g_return_val_if_fail( group != NULL, FALSE );
444 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
447 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
452 * Add folder to hash table.
453 * return: TRUE if item added.
455 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
456 g_return_val_if_fail( cache != NULL, FALSE );
457 g_return_val_if_fail( folder != NULL, FALSE );
459 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
462 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
467 * Add person to specified folder in cache.
469 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
470 gboolean retVal = FALSE;
472 g_return_val_if_fail( cache != NULL, FALSE );
473 g_return_val_if_fail( folder != NULL, FALSE );
474 g_return_val_if_fail( item != NULL, FALSE );
476 retVal = addrcache_hash_add_person( cache, item );
478 addritem_folder_add_person( folder, item );
479 cache->dirtyFlag = TRUE;
485 * Add folder to specified folder in cache.
487 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
488 gboolean retVal = FALSE;
490 g_return_val_if_fail( cache != NULL, FALSE );
491 g_return_val_if_fail( folder != NULL, FALSE );
492 g_return_val_if_fail( item != NULL, FALSE );
494 retVal = addrcache_hash_add_folder( cache, item );
496 addritem_folder_add_folder( folder, item );
497 cache->dirtyFlag = TRUE;
503 * Add folder to specified folder in cache.
505 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
506 gboolean retVal = FALSE;
508 g_return_val_if_fail( cache != NULL, FALSE );
509 g_return_val_if_fail( folder != NULL, FALSE );
510 g_return_val_if_fail( item != NULL, FALSE );
512 retVal = addrcache_hash_add_group( cache, item );
514 addritem_folder_add_group( folder, item );
515 cache->dirtyFlag = TRUE;
521 * Add person to address cache.
522 * return: TRUE if item added.
524 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
525 gboolean retVal = FALSE;
527 g_return_val_if_fail( cache != NULL, FALSE );
528 g_return_val_if_fail( person != NULL, FALSE );
530 retVal = addrcache_hash_add_person( cache, person );
532 addritem_folder_add_person( cache->rootFolder, person );
533 cache->dirtyFlag = TRUE;
539 * Add EMail address to person.
540 * return: TRUE if item added.
542 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
543 gboolean retVal = FALSE;
545 g_return_val_if_fail( cache != NULL, FALSE );
546 g_return_val_if_fail( person != NULL, FALSE );
547 g_return_val_if_fail( email != NULL, FALSE );
549 retVal = addrcache_hash_add_email( cache, email );
551 addritem_person_add_email( person, email );
552 cache->dirtyFlag = TRUE;
558 * Add group to address cache.
559 * return: TRUE if item added.
561 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
562 gboolean retVal = FALSE;
564 g_return_val_if_fail( cache != NULL, FALSE );
565 g_return_val_if_fail( group != NULL, FALSE );
567 retVal = addrcache_hash_add_group( cache, group );
569 addritem_folder_add_group( cache->rootFolder, group );
570 cache->dirtyFlag = TRUE;
576 * Add EMail address to person.
577 * return: TRUE if item added.
579 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
580 g_return_val_if_fail( cache != NULL, FALSE );
581 g_return_val_if_fail( group != NULL, FALSE );
582 g_return_val_if_fail( email != NULL, FALSE );
584 addritem_group_add_email( group, email );
585 cache->dirtyFlag = TRUE;
590 * Add folder to address cache.
591 * return: TRUE if item added.
593 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
594 gboolean retVal = FALSE;
596 g_return_val_if_fail( cache != NULL, FALSE );
597 g_return_val_if_fail( folder != NULL, FALSE );
599 retVal = addrcache_hash_add_folder( cache, folder );
601 addritem_folder_add_folder( cache->rootFolder, folder );
602 cache->dirtyFlag = TRUE;
608 * Move person to destination folder.
609 * Enter: cache Cache.
610 * person Person to move.
611 * target Target folder.
613 void addrcache_folder_move_person(
614 AddressCache *cache, ItemPerson *person, ItemFolder *target )
618 g_return_if_fail( cache != NULL );
619 g_return_if_fail( person != NULL );
621 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
622 if( ! parent ) parent = cache->rootFolder;
623 parent->listPerson = g_list_remove( parent->listPerson, person );
624 target->listPerson = g_list_append( target->listPerson, person );
625 ADDRITEM_PARENT(person) = ADDRITEM_OBJECT(target);
626 cache->dirtyFlag = TRUE;
630 * Move group to destination folder.
631 * Enter: cache Cache.
632 * group Group to move.
633 * target Target folder.
635 void addrcache_folder_move_group(
636 AddressCache *cache, ItemGroup *group, ItemFolder *target )
640 g_return_if_fail( cache != NULL );
641 g_return_if_fail( group != NULL );
643 parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
644 if( ! parent ) parent = cache->rootFolder;
645 parent->listGroup = g_list_remove( parent->listGroup, group );
646 target->listGroup = g_list_append( target->listGroup, group );
647 ADDRITEM_PARENT(group) = ADDRITEM_OBJECT(target);
648 cache->dirtyFlag = TRUE;
652 * Move folder to destination folder.
653 * Enter: cache Cache.
654 * folder Folder to move.
655 * target Target folder.
657 void addrcache_folder_move_folder(
658 AddressCache *cache, ItemFolder *folder, ItemFolder *target )
662 g_return_if_fail( cache != NULL );
663 g_return_if_fail( folder != NULL );
665 parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
666 if( ! parent ) parent = cache->rootFolder;
667 parent->listFolder = g_list_remove( parent->listFolder, folder );
668 target->listFolder = g_list_append( target->listFolder, folder );
669 ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(target);
670 cache->dirtyFlag = TRUE;
674 * Return pointer to object (either person or group) for specified ID.
675 * param: uid Object ID.
676 * return: Object, or NULL if not found.
678 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
679 AddrItemObject *obj = NULL;
682 g_return_val_if_fail( cache != NULL, NULL );
684 if( uid == NULL || *uid == '\0' ) return NULL;
685 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
687 /* Check for matching UID */
688 uidH = ADDRITEM_ID(obj);
690 if( strcmp( uidH, uid ) == 0 ) return obj;
697 * Return pointer for specified object ID.
698 * param: uid Object ID.
699 * return: Person object, or NULL if not found.
701 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
702 ItemPerson *person = NULL;
703 AddrItemObject *obj = addrcache_get_object( cache, uid );
706 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
707 person = ( ItemPerson * ) obj;
714 * Return pointer for specified object ID.
715 * param: uid group ID.
716 * return: Group object, or NULL if not found.
718 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
719 ItemGroup *group = NULL;
720 AddrItemObject *obj = addrcache_get_object( cache, uid );
723 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
724 group = ( ItemGroup * ) obj;
731 * Find email address in address cache.
732 * param: eid EMail ID.
733 * return: email object for specified object ID and email ID, or NULL if not found.
735 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *eid ) {
736 ItemEMail *email = NULL;
737 AddrItemObject *obj = addrcache_get_object( cache, eid );
740 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
741 email = ( ItemEMail * ) obj;
748 * Remove attribute from person.
749 * param: uid Object ID for person.
751 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
753 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
754 UserAttribute *attrib = NULL;
757 if( aid == NULL || *aid == '\0' ) return NULL;
759 person = addrcache_get_person( cache, uid );
761 attrib = addritem_person_remove_attrib_id( person, aid );
762 cache->dirtyFlag = TRUE;
768 * Remove attribute from person.
769 * param: person Person.
770 * attrib Attribute to remove.
771 * return: UserAttribute object. Note that object should still be freed.
773 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
774 UserAttribute *found = NULL;
776 g_return_val_if_fail( cache != NULL, NULL );
778 if( person && attrib ) {
779 found = addritem_person_remove_attribute( person, attrib );
780 cache->dirtyFlag = TRUE;
786 * Remove group from address cache.
787 * param: group Group to remove.
788 * return: Group, or NULL if not found. Note that object should still be freed.
790 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
791 AddrItemObject *obj = NULL;
793 g_return_val_if_fail( cache != NULL, NULL );
796 gchar *uid = ADDRITEM_ID(group);
797 if( uid == NULL || *uid == '\0' ) return NULL;
798 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
800 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
801 if( ! parent ) parent = cache->rootFolder;
803 /* Remove group from parent's list and hash table */
804 parent->listGroup = g_list_remove( parent->listGroup, obj );
805 g_hash_table_remove( cache->itemHash, uid );
806 cache->dirtyFlag = TRUE;
814 * Remove specified email from address cache. Note that object is only
815 * removed from cache and not parent objects.
816 * param: email EMail to remove.
817 * return: EMail, or NULL if not found. Note that object should still be freed.
819 ItemEMail *addrcache_remove_email( AddressCache *cache, ItemEMail *email ) {
820 AddrItemObject *obj = NULL;
822 g_return_val_if_fail( cache != NULL, NULL );
825 gchar *eid = ADDRITEM_ID(email);
826 if( eid == NULL || *eid == '\0' ) return NULL;
827 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, eid );
829 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
830 /* Remove email addresses from hash table. */
831 g_hash_table_remove( cache->itemHash, eid );
832 cache->dirtyFlag = TRUE;
841 * Hash table visitor function to remove email from group.
843 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
844 AddrItemObject *obj = ( AddrItemObject * ) value;
845 ItemEMail *email = ( ItemEMail * ) data;
847 if( ! email ) return;
848 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
849 ItemGroup *group = ( ItemGroup * ) value;
851 /* Remove each email address that belongs to the person from the list */
852 group->listEMail = g_list_remove( group->listEMail, email );
858 * Remove specified person from address cache.
859 * param: person Person to remove.
860 * return: Person, or NULL if not found. Note that object should still be freed.
862 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
863 AddrItemObject *obj = NULL;
866 g_return_val_if_fail( cache != NULL, NULL );
869 uid = ADDRITEM_ID(person);
870 if( uid == NULL || *uid == '\0' ) return NULL;
871 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
873 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
877 /* Remove all email addresses for person */
878 /* from groups and from hash table */
879 node = person->listEMail;
885 g_hash_table_foreach( cache->itemHash,
886 addrcache_allgrp_rem_email_vis, email );
887 eid = ADDRITEM_ID( email );
888 g_hash_table_remove( cache->itemHash, eid );
889 node = g_list_next( node );
892 /* Remove person from owning folder */
893 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
894 if( ! parent ) parent = cache->rootFolder;
895 parent->listPerson = g_list_remove( parent->listPerson, person );
896 g_hash_table_remove( cache->itemHash, uid );
897 cache->dirtyFlag = TRUE;
906 * Remove email address in address cache for specified person.
907 * param: person Person.
908 * email EMail to remove.
909 * return: EMail object, or NULL if not found. Note that object should still be freed.
911 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
912 ItemEMail *found = NULL;
914 g_return_val_if_fail( cache != NULL, NULL );
916 if( person && email ) {
917 found = addritem_person_remove_email( person, email );
919 /* Remove email from all groups. */
920 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
922 /* Remove email from person's address list */
923 if( person->listEMail ) {
924 person->listEMail = g_list_remove( person->listEMail, email );
926 /* Unlink reference to person. */
927 ADDRITEM_PARENT(email) = NULL;
928 cache->dirtyFlag = TRUE;
935 * Move email address in address cache to new person. If member of group, address
937 * param: cache Cache.
938 * email EMail to remove.
939 * target Target person.
940 * return: EMail object, or NULL if not found. Note that object should still be freed.
942 void addrcache_person_move_email(
943 AddressCache *cache, ItemEMail *email, ItemPerson *target )
947 g_return_if_fail( cache != NULL );
949 if( email == NULL ) return;
950 if( target == NULL ) return;
952 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
955 found = addritem_person_remove_email( person, email );
957 if( person->listEMail ) {
958 person->listEMail = g_list_remove( person->listEMail, found );
959 addritem_person_add_email( target, found );
960 cache->dirtyFlag = TRUE;
967 * Return link list of address items for root level folder. Note that the list contains
968 * references to items and should be g_free() when done. Do *NOT* attempt to use the
969 * addrcache_free_xxx() functions... this will destroy the address cache data!
970 * Return: List of items, or NULL if none.
972 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
975 ItemFolder *f = folder;
977 g_return_val_if_fail( cache != NULL, NULL );
979 if( ! f ) f = cache->rootFolder;
980 node = f->listPerson;
982 list = g_list_append( list, node->data );
983 node = g_list_next( node );
987 list = g_list_append( list, node->data );
988 node = g_list_next( node );
994 * Return link list of persons for specified folder. Note that the list contains
995 * references to items and should be g_free() when done. Do *NOT* attempt to use the
996 * addrcache_free_xxx() functions... this will destroy the address cache data!
997 * Return: List of items, or NULL if none.
999 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
1000 ItemFolder *f = folder;
1002 g_return_val_if_fail( cache != NULL, NULL );
1004 if( ! f ) f = cache->rootFolder;
1005 return addritem_folder_get_person_list( f );
1009 * Return link list of group items for specified folder. Note that the list contains
1010 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1011 * addrcache_free_xxx() functions... this will destroy the address cache data!
1012 * Return: List of items, or NULL if none.
1014 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
1015 ItemFolder *f = folder;
1017 g_return_val_if_fail( cache != NULL, NULL );
1019 if( ! f ) f = cache->rootFolder;
1020 return addritem_folder_get_group_list( f );
1024 * Return link list of folder items for specified folder. Note that the list contains
1025 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1026 * addrcache_free_xxx() functions... this will destroy the address cache data!
1027 * Return: List of items, or NULL if none.
1029 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
1032 ItemFolder *f = folder;
1034 g_return_val_if_fail( cache != NULL, NULL );
1036 if( ! f ) f = cache->rootFolder;
1037 node = f->listFolder;
1039 list = g_list_append( list, node->data );
1040 node = g_list_next( node );
1046 * Return link list of address items for root level folder. Note that the list contains
1047 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1048 * addrcache_free_xxx() functions... this will destroy the address cache data!
1049 * Return: List of items, or NULL if none.
1051 GList *addrcache_get_address_list( AddressCache *cache ) {
1052 g_return_val_if_fail( cache != NULL, NULL );
1053 return addrcache_folder_get_address_list( cache, cache->rootFolder );
1057 * Return link list of persons for root level folder. Note that the list contains
1058 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1059 * addrcache_free_xxx() functions... this will destroy the address cache data!
1060 * Return: List of items, or NULL if none.
1062 GList *addrcache_get_person_list( AddressCache *cache ) {
1063 g_return_val_if_fail( cache != NULL, NULL );
1064 return addritem_folder_get_person_list( cache->rootFolder );
1068 * Return link list of group items in root level folder. Note that the list contains
1069 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1070 * addrcache_free_xxx() functions... this will destroy the address cache data!
1071 * Return: List of items, or NULL if none.
1073 GList *addrcache_get_group_list( AddressCache *cache ) {
1074 g_return_val_if_fail( cache != NULL, NULL );
1075 return cache->rootFolder->listGroup;
1079 * Return link list of folder items in root level folder. Note that the list contains
1080 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1081 * addrcache_free_xxx() functions... this will destroy the address cache data!
1082 * Return: List of items, or NULL if none.
1084 GList *addrcache_get_folder_list( AddressCache *cache ) {
1085 g_return_val_if_fail( cache != NULL, NULL );
1086 return cache->rootFolder->listFolder;
1090 * Group visitor function.
1092 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
1093 AddrItemObject *obj = ( AddrItemObject * ) value;
1095 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1096 AddressCache *cache = data;
1097 ItemGroup *group = ( ItemGroup * ) obj;
1098 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
1099 GList *node = group->listEMail;
1101 ItemEMail *email = ( ItemEMail * ) node->data;
1102 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
1103 if( ! g_list_find( cache->tempList, group ) ) {
1104 cache->tempList = g_list_append( cache->tempList, group );
1107 node = g_list_next( node );
1113 * Return linked list of groups which contain a reference to specified person's email
1116 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
1119 g_return_val_if_fail( cache != NULL, NULL );
1121 cache->tempList = NULL;
1122 cache->tempList = g_list_append( cache->tempList, person );
1123 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
1124 cache->tempList = g_list_remove( cache->tempList, person );
1125 list = cache->tempList;
1126 cache->tempList = NULL;
1131 * Find root folder for specified folder.
1132 * Enter: folder Folder to search.
1133 * Return: root folder, or NULL if not found.
1135 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1136 ItemFolder *item = folder;
1140 if( item->isRoot ) break;
1141 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1145 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1151 * Get all person visitor function.
1153 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1154 AddrItemObject *obj = ( AddrItemObject * ) value;
1156 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1157 AddressCache *cache = data;
1158 cache->tempList = g_list_append( cache->tempList, obj );
1163 * Return link list of all persons in address cache. Note that the list contains
1164 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1165 * this will destroy the address cache data!
1166 * Return: List of items, or NULL if none.
1168 GList *addrcache_get_all_persons( AddressCache *cache ) {
1171 g_return_val_if_fail( cache != NULL, NULL );
1173 cache->tempList = NULL;
1174 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1175 list = cache->tempList;
1176 cache->tempList = NULL;
1181 * Get all groups visitor function.
1183 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1184 AddrItemObject *obj = ( AddrItemObject * ) value;
1186 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1187 AddressCache *cache = data;
1188 cache->tempList = g_list_append( cache->tempList, obj );
1193 * Return link list of all groups in address cache. Note that the list contains
1194 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1195 * this will destroy the address cache data!
1196 * Return: List of items, or NULL if none.
1198 GList *addrcache_get_all_groups( AddressCache *cache ) {
1201 g_return_val_if_fail( cache != NULL, NULL );
1203 cache->tempList = NULL;
1204 g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1205 list = cache->tempList;
1206 cache->tempList = NULL;
1211 * Remove folder from cache. Children are re-parented to parent folder.
1212 * param: folder Folder to remove.
1213 * return: Folder, or NULL if not found. Note that object should still be freed.
1215 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1216 AddrItemObject *obj = NULL;
1218 g_return_val_if_fail( cache != NULL, NULL );
1221 gchar *uid = ADDRITEM_ID(folder);
1222 if( uid == NULL || *uid == '\0' ) return NULL;
1223 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1225 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1227 AddrItemObject *aio;
1228 if( ! parent ) parent = cache->rootFolder;
1230 /* Re-parent children in folder */
1231 node = folder->listFolder;
1233 aio = ( AddrItemObject * ) node->data;
1234 parent->listFolder = g_list_append( parent->listFolder, aio );
1235 aio->parent = ADDRITEM_OBJECT(parent);
1236 node = g_list_next( node );
1238 node = folder->listPerson;
1240 aio = ( AddrItemObject * ) node->data;
1241 parent->listPerson = g_list_append( parent->listPerson, aio );
1242 aio->parent = ADDRITEM_OBJECT(parent);
1243 node = g_list_next( node );
1245 node = folder->listGroup;
1247 aio = ( AddrItemObject * ) node->data;
1248 parent->listGroup = g_list_append( parent->listGroup, aio );
1249 aio->parent = ADDRITEM_OBJECT(parent);
1250 node = g_list_next( node );
1253 /* Remove folder from parent's list and hash table */
1254 parent->listFolder = g_list_remove( parent->listFolder, folder );
1255 ADDRITEM_PARENT(folder) = NULL;
1256 g_hash_table_remove( cache->itemHash, uid );
1257 cache->dirtyFlag = TRUE;
1265 * Remove folder from cache. Children are deleted.
1266 * param: folder Folder to remove.
1267 * return: Folder, or NULL if not found. Note that object should still be freed.
1269 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1270 AddrItemObject *obj = NULL;
1272 g_return_val_if_fail( cache != NULL, NULL );
1275 gchar *uid = ADDRITEM_ID(folder);
1276 if( uid == NULL || *uid == '\0' ) return NULL;
1277 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1279 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1280 if( ! parent ) parent = cache->rootFolder;
1283 while( folder->listGroup ) {
1284 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1285 item = addrcache_remove_group( cache, item );
1287 addritem_free_item_group( item );
1292 while( folder->listPerson ) {
1293 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1294 item = addrcache_remove_person( cache, item );
1296 addritem_free_item_person( item );
1301 /* Recursive deletion of folder */
1302 while( folder->listFolder ) {
1303 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1304 item = addrcache_remove_folder_delete( cache, item );
1306 addritem_free_item_folder( item );
1311 /* Remove folder from parent's list and hash table */
1312 parent->listFolder = g_list_remove( parent->listFolder, folder );
1313 ADDRITEM_PARENT(folder) = NULL;
1314 g_hash_table_remove( cache->itemHash, uid );
1315 cache->dirtyFlag = TRUE;
1323 * Add person and address data to cache.
1324 * Enter: cache Cache.
1325 * folder Folder where to add person, or NULL for root folder.
1327 * address EMail address.
1329 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1330 * this will destroy the address book data.
1332 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1333 const gchar *address, const gchar *remarks )
1335 ItemPerson *person = NULL;
1336 ItemEMail *email = NULL;
1337 ItemFolder *f = folder;
1339 g_return_val_if_fail( cache != NULL, NULL );
1341 if( ! f ) f = cache->rootFolder;
1343 /* Create person object */
1344 person = addritem_create_item_person();
1345 addritem_person_set_common_name( person, name );
1346 addrcache_id_person( cache, person );
1347 addrcache_folder_add_person( cache, f, person );
1349 /* Create email object */
1350 email = addritem_create_item_email();
1351 addritem_email_set_address( email, address );
1352 addritem_email_set_remarks( email, remarks );
1353 addrcache_id_email( cache, email );
1354 addritem_person_add_email( person, email );
1355 cache->dirtyFlag = TRUE;