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 );
186 g_hash_table_destroy( table );
190 * Free up folders and groups.
192 static void addrcache_free_all_folders( ItemFolder *parent ) {
193 GList *node = parent->listFolder;
195 ItemFolder *folder = node->data;
196 addrcache_free_all_folders( folder );
197 node = g_list_next( node );
199 g_list_free( parent->listPerson );
200 g_list_free( parent->listGroup );
201 g_list_free( parent->listFolder );
202 parent->listPerson = NULL;
203 parent->listGroup = NULL;
204 parent->listFolder = NULL;
208 * Clear the address cache.
210 void addrcache_clear( AddressCache *cache ) {
211 g_return_if_fail( cache != NULL );
213 /* printf( "...addrcache_clear :%s:\n", cache->name ); */
214 /* Free up folders and hash table */
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;
224 /* Reset to initial state */
225 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
226 cache->rootFolder = addritem_create_item_folder();
227 cache->rootFolder->isRoot = TRUE;
228 ADDRITEM_PARENT(cache->rootFolder) = NULL;
230 addrcache_refresh( cache );
235 * Free address cache.
237 void addrcache_free( AddressCache *cache ) {
238 g_return_if_fail( cache != NULL );
240 cache->dirtyFlag = FALSE;
241 addrcache_free_all_folders( cache->rootFolder );
242 addrcache_free_item_hash( cache->itemHash );
243 cache->itemHash = NULL;
244 ADDRITEM_PARENT(cache->rootFolder) = NULL;
245 addritem_free_item_folder( cache->rootFolder );
246 cache->rootFolder = NULL;
247 g_list_free( cache->tempList );
248 cache->tempList = NULL;
249 g_free( cache->cacheID );
250 cache->cacheID = NULL;
251 g_free( cache->name );
257 * Check whether file has changed by comparing with cache.
258 * return: TRUE if file has changed.
260 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
262 struct stat filestat;
265 if( 0 == lstat( path, &filestat ) ) {
266 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
273 * Save file time to cache.
274 * return: TRUE if time marked.
276 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
277 gboolean retVal = FALSE;
278 struct stat filestat;
280 if( 0 == lstat( path, &filestat ) ) {
281 cache->modifyTime = filestat.st_mtime;
289 * Print list of items.
291 void addrcache_print_item_list( GList *list, FILE *stream ) {
294 AddrItemObject *obj = node->data;
295 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
296 addritem_print_item_person( ( ItemPerson * ) obj, stream );
298 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
299 addritem_print_item_group( ( ItemGroup * ) obj, stream );
301 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
302 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
304 node = g_list_next( node );
306 fprintf( stream, "\t---\n" );
310 * Print item hash table visitor function.
312 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
313 AddrItemObject *obj = ( AddrItemObject * ) value;
314 FILE *stream = ( FILE * ) data;
315 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
316 addritem_print_item_person( ( ItemPerson * ) obj, stream );
318 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
319 printf( "addrcache: print email\n" );
321 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
322 addritem_print_item_group( ( ItemGroup * ) obj, stream );
324 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
325 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
330 * Dump entire address cache hash table contents.
332 void addrcache_print( AddressCache *cache, FILE *stream ) {
333 g_return_if_fail( cache != NULL );
334 fprintf( stream, "AddressCache:\n" );
335 fprintf( stream, "cache id : %s\n", cache->cacheID );
336 fprintf( stream, "next id : %d\n", cache->nextID );
337 fprintf( stream, "name : %s\n", cache->name );
338 fprintf( stream, "mod time : %ld\n", cache->modifyTime );
339 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
340 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
344 * Dump entire address cache hash table contents.
346 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
347 g_return_if_fail( cache != NULL );
348 addrcache_print( cache, stream );
349 g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
353 * Allocate ID for person.
355 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
356 g_return_if_fail( cache != NULL );
357 g_return_if_fail( person != NULL );
358 if( ADDRITEM_ID(person) ) return;
359 addrcache_next_id( cache );
360 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
364 * Allocate ID for group.
366 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
367 g_return_if_fail( cache != NULL );
368 g_return_if_fail( group != NULL );
369 if( ADDRITEM_ID(group) ) return;
370 addrcache_next_id( cache );
371 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
375 * Allocate ID for folder.
377 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
378 g_return_if_fail( cache != NULL );
379 g_return_if_fail( folder != NULL );
380 if( ADDRITEM_ID(folder) ) return;
381 addrcache_next_id( cache );
382 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
386 * Allocate ID for email address.
388 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
389 g_return_if_fail( cache != NULL );
390 g_return_if_fail( email != NULL );
391 if( ADDRITEM_ID(email) ) return;
392 addrcache_next_id( cache );
393 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
397 * Allocate ID for user attribute.
399 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
400 g_return_if_fail( cache != NULL );
401 g_return_if_fail( attrib != NULL );
402 if( attrib->uid ) return;
403 addrcache_next_id( cache );
404 attrib->uid = g_strdup_printf( "%d", cache->nextID );
408 * Add person to hash table.
409 * return: TRUE if item added.
411 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
412 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
415 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
420 * Add email to hash table.
421 * return: TRUE if item added.
423 gboolean addrcache_hash_add_email( AddressCache *cache, ItemEMail *email ) {
424 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(email) ) ) {
427 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(email), email );
432 * Add group to hash table.
433 * return: TRUE if item added.
435 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
436 g_return_val_if_fail( cache != NULL, FALSE );
437 g_return_val_if_fail( group != NULL, FALSE );
439 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
442 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
447 * Add folder to hash table.
448 * return: TRUE if item added.
450 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
451 g_return_val_if_fail( cache != NULL, FALSE );
452 g_return_val_if_fail( folder != NULL, FALSE );
454 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
457 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
462 * Add person to specified folder in cache.
464 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
465 gboolean retVal = FALSE;
467 g_return_val_if_fail( cache != NULL, FALSE );
468 g_return_val_if_fail( folder != NULL, FALSE );
469 g_return_val_if_fail( item != NULL, FALSE );
471 retVal = addrcache_hash_add_person( cache, item );
473 addritem_folder_add_person( folder, item );
474 cache->dirtyFlag = TRUE;
480 * Add folder to specified folder in cache.
482 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
483 gboolean retVal = FALSE;
485 g_return_val_if_fail( cache != NULL, FALSE );
486 g_return_val_if_fail( folder != NULL, FALSE );
487 g_return_val_if_fail( item != NULL, FALSE );
489 retVal = addrcache_hash_add_folder( cache, item );
491 addritem_folder_add_folder( folder, item );
492 cache->dirtyFlag = TRUE;
498 * Add folder to specified folder in cache.
500 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
501 gboolean retVal = FALSE;
503 g_return_val_if_fail( cache != NULL, FALSE );
504 g_return_val_if_fail( folder != NULL, FALSE );
505 g_return_val_if_fail( item != NULL, FALSE );
507 retVal = addrcache_hash_add_group( cache, item );
509 addritem_folder_add_group( folder, item );
510 cache->dirtyFlag = TRUE;
516 * Add person to address cache.
517 * return: TRUE if item added.
519 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
520 gboolean retVal = FALSE;
522 g_return_val_if_fail( cache != NULL, FALSE );
523 g_return_val_if_fail( person != NULL, FALSE );
525 retVal = addrcache_hash_add_person( cache, person );
527 addritem_folder_add_person( cache->rootFolder, person );
528 cache->dirtyFlag = TRUE;
534 * Add EMail address to person.
535 * return: TRUE if item added.
537 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
538 gboolean retVal = FALSE;
540 g_return_val_if_fail( cache != NULL, FALSE );
541 g_return_val_if_fail( person != NULL, FALSE );
542 g_return_val_if_fail( email != NULL, FALSE );
544 retVal = addrcache_hash_add_email( cache, email );
546 addritem_person_add_email( person, email );
547 cache->dirtyFlag = TRUE;
553 * Add group to address cache.
554 * return: TRUE if item added.
556 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
557 gboolean retVal = FALSE;
559 g_return_val_if_fail( cache != NULL, FALSE );
560 g_return_val_if_fail( group != NULL, FALSE );
562 retVal = addrcache_hash_add_group( cache, group );
564 addritem_folder_add_group( cache->rootFolder, group );
565 cache->dirtyFlag = TRUE;
571 * Add EMail address to person.
572 * return: TRUE if item added.
574 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
575 g_return_val_if_fail( cache != NULL, FALSE );
576 g_return_val_if_fail( group != NULL, FALSE );
577 g_return_val_if_fail( email != NULL, FALSE );
579 addritem_group_add_email( group, email );
580 cache->dirtyFlag = TRUE;
585 * Add folder to address cache.
586 * return: TRUE if item added.
588 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
589 gboolean retVal = FALSE;
591 g_return_val_if_fail( cache != NULL, FALSE );
592 g_return_val_if_fail( folder != NULL, FALSE );
594 retVal = addrcache_hash_add_folder( cache, folder );
596 addritem_folder_add_folder( cache->rootFolder, folder );
597 cache->dirtyFlag = TRUE;
603 * Move person to destination folder.
604 * Enter: cache Cache.
605 * person Person to move.
606 * target Target folder.
608 void addrcache_folder_move_person(
609 AddressCache *cache, ItemPerson *person, ItemFolder *target )
613 g_return_if_fail( cache != NULL );
614 g_return_if_fail( person != NULL );
616 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
617 if( ! parent ) parent = cache->rootFolder;
618 parent->listPerson = g_list_remove( parent->listPerson, person );
619 target->listPerson = g_list_append( target->listPerson, person );
620 ADDRITEM_PARENT(person) = ADDRITEM_OBJECT(target);
621 cache->dirtyFlag = TRUE;
625 * Move group to destination folder.
626 * Enter: cache Cache.
627 * group Group to move.
628 * target Target folder.
630 void addrcache_folder_move_group(
631 AddressCache *cache, ItemGroup *group, ItemFolder *target )
635 g_return_if_fail( cache != NULL );
636 g_return_if_fail( group != NULL );
638 parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
639 if( ! parent ) parent = cache->rootFolder;
640 parent->listGroup = g_list_remove( parent->listGroup, group );
641 target->listGroup = g_list_append( target->listGroup, group );
642 ADDRITEM_PARENT(group) = ADDRITEM_OBJECT(target);
643 cache->dirtyFlag = TRUE;
647 * Move folder to destination folder.
648 * Enter: cache Cache.
649 * folder Folder to move.
650 * target Target folder.
652 void addrcache_folder_move_folder(
653 AddressCache *cache, ItemFolder *folder, ItemFolder *target )
657 g_return_if_fail( cache != NULL );
658 g_return_if_fail( folder != NULL );
660 parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
661 if( ! parent ) parent = cache->rootFolder;
662 parent->listFolder = g_list_remove( parent->listFolder, folder );
663 target->listFolder = g_list_append( target->listFolder, folder );
664 ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(target);
665 cache->dirtyFlag = TRUE;
669 * Return pointer to object (either person or group) for specified ID.
670 * param: uid Object ID.
671 * return: Object, or NULL if not found.
673 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
674 AddrItemObject *obj = NULL;
677 g_return_val_if_fail( cache != NULL, NULL );
679 if( uid == NULL || *uid == '\0' ) return NULL;
680 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
682 /* Check for matching UID */
683 uidH = ADDRITEM_ID(obj);
685 if( strcmp( uidH, uid ) == 0 ) return obj;
692 * Return pointer for specified object ID.
693 * param: uid Object ID.
694 * return: Person object, or NULL if not found.
696 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
697 ItemPerson *person = NULL;
698 AddrItemObject *obj = addrcache_get_object( cache, uid );
701 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
702 person = ( ItemPerson * ) obj;
709 * Return pointer for specified object ID.
710 * param: uid group ID.
711 * return: Group object, or NULL if not found.
713 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
714 ItemGroup *group = NULL;
715 AddrItemObject *obj = addrcache_get_object( cache, uid );
718 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
719 group = ( ItemGroup * ) obj;
726 * Find email address in address cache.
727 * param: eid EMail ID.
728 * return: email object for specified object ID and email ID, or NULL if not found.
730 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *eid ) {
731 ItemEMail *email = NULL;
732 AddrItemObject *obj = addrcache_get_object( cache, eid );
735 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
736 email = ( ItemEMail * ) obj;
743 * Remove attribute from person.
744 * param: uid Object ID for person.
746 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
748 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
749 UserAttribute *attrib = NULL;
752 if( aid == NULL || *aid == '\0' ) return NULL;
754 person = addrcache_get_person( cache, uid );
756 attrib = addritem_person_remove_attrib_id( person, aid );
757 cache->dirtyFlag = TRUE;
763 * Remove attribute from person.
764 * param: person Person.
765 * attrib Attribute to remove.
766 * return: UserAttribute object. Note that object should still be freed.
768 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
769 UserAttribute *found = NULL;
771 g_return_val_if_fail( cache != NULL, NULL );
773 if( person && attrib ) {
774 found = addritem_person_remove_attribute( person, attrib );
775 cache->dirtyFlag = TRUE;
781 * Remove group from address cache.
782 * param: group Group to remove.
783 * return: Group, or NULL if not found. Note that object should still be freed.
785 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
786 AddrItemObject *obj = NULL;
788 g_return_val_if_fail( cache != NULL, NULL );
791 gchar *uid = ADDRITEM_ID(group);
792 if( uid == NULL || *uid == '\0' ) return NULL;
793 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
795 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
796 if( ! parent ) parent = cache->rootFolder;
798 /* Remove group from parent's list and hash table */
799 parent->listGroup = g_list_remove( parent->listGroup, obj );
800 g_hash_table_remove( cache->itemHash, uid );
801 cache->dirtyFlag = TRUE;
809 * Remove specified email from address cache. Note that object is only
810 * removed from cache and not parent objects.
811 * param: email EMail to remove.
812 * return: EMail, or NULL if not found. Note that object should still be freed.
814 ItemEMail *addrcache_remove_email( AddressCache *cache, ItemEMail *email ) {
815 AddrItemObject *obj = NULL;
817 g_return_val_if_fail( cache != NULL, NULL );
820 gchar *eid = ADDRITEM_ID(email);
821 if( eid == NULL || *eid == '\0' ) return NULL;
822 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, eid );
824 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
825 /* Remove email addresses from hash table. */
826 g_hash_table_remove( cache->itemHash, eid );
827 cache->dirtyFlag = TRUE;
836 * Hash table visitor function to remove email from group.
838 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
839 AddrItemObject *obj = ( AddrItemObject * ) value;
840 ItemEMail *email = ( ItemEMail * ) data;
842 if( ! email ) return;
843 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
844 ItemGroup *group = ( ItemGroup * ) value;
846 /* Remove each email address that belongs to the person from the list */
847 group->listEMail = g_list_remove( group->listEMail, email );
853 * Remove specified person from address cache.
854 * param: person Person to remove.
855 * return: Person, or NULL if not found. Note that object should still be freed.
857 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
858 AddrItemObject *obj = NULL;
861 g_return_val_if_fail( cache != NULL, NULL );
864 uid = ADDRITEM_ID(person);
865 if( uid == NULL || *uid == '\0' ) return NULL;
866 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
868 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
872 /* Remove all email addresses for person */
873 /* from groups and from hash table */
874 node = person->listEMail;
880 g_hash_table_foreach( cache->itemHash,
881 addrcache_allgrp_rem_email_vis, email );
882 eid = ADDRITEM_ID( email );
883 g_hash_table_remove( cache->itemHash, eid );
884 node = g_list_next( node );
887 /* Remove person from owning folder */
888 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
889 if( ! parent ) parent = cache->rootFolder;
890 parent->listPerson = g_list_remove( parent->listPerson, person );
891 g_hash_table_remove( cache->itemHash, uid );
892 cache->dirtyFlag = TRUE;
901 * Remove email address in address cache for specified person.
902 * param: person Person.
903 * email EMail to remove.
904 * return: EMail object, or NULL if not found. Note that object should still be freed.
906 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
907 ItemEMail *found = NULL;
909 g_return_val_if_fail( cache != NULL, NULL );
911 if( person && email ) {
912 found = addritem_person_remove_email( person, email );
914 /* Remove email from all groups. */
915 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
917 /* Remove email from person's address list */
918 if( person->listEMail ) {
919 person->listEMail = g_list_remove( person->listEMail, email );
921 /* Unlink reference to person. */
922 ADDRITEM_PARENT(email) = NULL;
923 cache->dirtyFlag = TRUE;
930 * Move email address in address cache to new person. If member of group, address
932 * param: cache Cache.
933 * email EMail to remove.
934 * target Target person.
935 * return: EMail object, or NULL if not found. Note that object should still be freed.
937 void addrcache_person_move_email(
938 AddressCache *cache, ItemEMail *email, ItemPerson *target )
942 g_return_if_fail( cache != NULL );
944 if( email == NULL ) return;
945 if( target == NULL ) return;
947 person = ( ItemPerson * ) ADDRITEM_PARENT(email);
950 found = addritem_person_remove_email( person, email );
952 if( person->listEMail ) {
953 person->listEMail = g_list_remove( person->listEMail, found );
954 addritem_person_add_email( target, found );
955 cache->dirtyFlag = TRUE;
962 * Return link list of address items for root level folder. Note that the list contains
963 * references to items and should be g_free() when done. Do *NOT* attempt to use the
964 * addrcache_free_xxx() functions... this will destroy the address cache data!
965 * Return: List of items, or NULL if none.
967 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
970 ItemFolder *f = folder;
972 g_return_val_if_fail( cache != NULL, NULL );
974 if( ! f ) f = cache->rootFolder;
975 node = f->listPerson;
977 list = g_list_append( list, node->data );
978 node = g_list_next( node );
982 list = g_list_append( list, node->data );
983 node = g_list_next( node );
989 * Return link list of persons for specified folder. Note that the list contains
990 * references to items and should be g_free() when done. Do *NOT* attempt to use the
991 * addrcache_free_xxx() functions... this will destroy the address cache data!
992 * Return: List of items, or NULL if none.
994 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
995 ItemFolder *f = folder;
997 g_return_val_if_fail( cache != NULL, NULL );
999 if( ! f ) f = cache->rootFolder;
1000 return addritem_folder_get_person_list( f );
1004 * Return link list of group items for specified folder. Note that the list contains
1005 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1006 * addrcache_free_xxx() functions... this will destroy the address cache data!
1007 * Return: List of items, or NULL if none.
1009 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
1010 ItemFolder *f = folder;
1012 g_return_val_if_fail( cache != NULL, NULL );
1014 if( ! f ) f = cache->rootFolder;
1015 return addritem_folder_get_group_list( f );
1019 * Return link list of folder items for specified folder. Note that the list contains
1020 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1021 * addrcache_free_xxx() functions... this will destroy the address cache data!
1022 * Return: List of items, or NULL if none.
1024 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
1027 ItemFolder *f = folder;
1029 g_return_val_if_fail( cache != NULL, NULL );
1031 if( ! f ) f = cache->rootFolder;
1032 node = f->listFolder;
1034 list = g_list_append( list, node->data );
1035 node = g_list_next( node );
1041 * Return link list of address items for root level folder. Note that the list contains
1042 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1043 * addrcache_free_xxx() functions... this will destroy the address cache data!
1044 * Return: List of items, or NULL if none.
1046 GList *addrcache_get_address_list( AddressCache *cache ) {
1047 g_return_val_if_fail( cache != NULL, NULL );
1048 return addrcache_folder_get_address_list( cache, cache->rootFolder );
1052 * Return link list of persons for root level folder. Note that the list contains
1053 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1054 * addrcache_free_xxx() functions... this will destroy the address cache data!
1055 * Return: List of items, or NULL if none.
1057 GList *addrcache_get_person_list( AddressCache *cache ) {
1058 g_return_val_if_fail( cache != NULL, NULL );
1059 return addritem_folder_get_person_list( cache->rootFolder );
1063 * Return link list of group items in root level folder. Note that the list contains
1064 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1065 * addrcache_free_xxx() functions... this will destroy the address cache data!
1066 * Return: List of items, or NULL if none.
1068 GList *addrcache_get_group_list( AddressCache *cache ) {
1069 g_return_val_if_fail( cache != NULL, NULL );
1070 return cache->rootFolder->listGroup;
1074 * Return link list of folder items in root level folder. Note that the list contains
1075 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1076 * addrcache_free_xxx() functions... this will destroy the address cache data!
1077 * Return: List of items, or NULL if none.
1079 GList *addrcache_get_folder_list( AddressCache *cache ) {
1080 g_return_val_if_fail( cache != NULL, NULL );
1081 return cache->rootFolder->listFolder;
1085 * Group visitor function.
1087 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
1088 AddrItemObject *obj = ( AddrItemObject * ) value;
1090 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1091 AddressCache *cache = data;
1092 ItemGroup *group = ( ItemGroup * ) obj;
1093 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
1094 GList *node = group->listEMail;
1096 ItemEMail *email = ( ItemEMail * ) node->data;
1097 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
1098 if( ! g_list_find( cache->tempList, group ) ) {
1099 cache->tempList = g_list_append( cache->tempList, group );
1102 node = g_list_next( node );
1108 * Return linked list of groups which contain a reference to specified person's email
1111 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
1114 g_return_val_if_fail( cache != NULL, NULL );
1116 cache->tempList = NULL;
1117 cache->tempList = g_list_append( cache->tempList, person );
1118 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
1119 cache->tempList = g_list_remove( cache->tempList, person );
1120 list = cache->tempList;
1121 cache->tempList = NULL;
1126 * Find root folder for specified folder.
1127 * Enter: folder Folder to search.
1128 * Return: root folder, or NULL if not found.
1130 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1131 ItemFolder *item = folder;
1135 if( item->isRoot ) break;
1136 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1140 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1146 * Get all person visitor function.
1148 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1149 AddrItemObject *obj = ( AddrItemObject * ) value;
1151 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1152 AddressCache *cache = data;
1153 cache->tempList = g_list_append( cache->tempList, obj );
1158 * Return link list of all persons in address cache. Note that the list contains
1159 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1160 * this will destroy the address cache data!
1161 * Return: List of items, or NULL if none.
1163 GList *addrcache_get_all_persons( AddressCache *cache ) {
1166 g_return_val_if_fail( cache != NULL, NULL );
1168 cache->tempList = NULL;
1169 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1170 list = cache->tempList;
1171 cache->tempList = NULL;
1176 * Get all groups visitor function.
1178 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1179 AddrItemObject *obj = ( AddrItemObject * ) value;
1181 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1182 AddressCache *cache = data;
1183 cache->tempList = g_list_append( cache->tempList, obj );
1188 * Return link list of all groups in address cache. Note that the list contains
1189 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1190 * this will destroy the address cache data!
1191 * Return: List of items, or NULL if none.
1193 GList *addrcache_get_all_groups( AddressCache *cache ) {
1196 g_return_val_if_fail( cache != NULL, NULL );
1198 cache->tempList = NULL;
1199 g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1200 list = cache->tempList;
1201 cache->tempList = NULL;
1206 * Remove folder from cache. Children are re-parented to parent folder.
1207 * param: folder Folder to remove.
1208 * return: Folder, or NULL if not found. Note that object should still be freed.
1210 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1211 AddrItemObject *obj = NULL;
1213 g_return_val_if_fail( cache != NULL, NULL );
1216 gchar *uid = ADDRITEM_ID(folder);
1217 if( uid == NULL || *uid == '\0' ) return NULL;
1218 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1220 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1222 AddrItemObject *aio;
1223 if( ! parent ) parent = cache->rootFolder;
1225 /* Re-parent children in folder */
1226 node = folder->listFolder;
1228 aio = ( AddrItemObject * ) node->data;
1229 parent->listFolder = g_list_append( parent->listFolder, aio );
1230 aio->parent = ADDRITEM_OBJECT(parent);
1231 node = g_list_next( node );
1233 node = folder->listPerson;
1235 aio = ( AddrItemObject * ) node->data;
1236 parent->listPerson = g_list_append( parent->listPerson, aio );
1237 aio->parent = ADDRITEM_OBJECT(parent);
1238 node = g_list_next( node );
1240 node = folder->listGroup;
1242 aio = ( AddrItemObject * ) node->data;
1243 parent->listGroup = g_list_append( parent->listGroup, aio );
1244 aio->parent = ADDRITEM_OBJECT(parent);
1245 node = g_list_next( node );
1248 /* Remove folder from parent's list and hash table */
1249 parent->listFolder = g_list_remove( parent->listFolder, folder );
1250 ADDRITEM_PARENT(folder) = NULL;
1251 g_hash_table_remove( cache->itemHash, uid );
1252 cache->dirtyFlag = TRUE;
1260 * Remove folder from cache. Children are deleted.
1261 * param: folder Folder to remove.
1262 * return: Folder, or NULL if not found. Note that object should still be freed.
1264 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1265 AddrItemObject *obj = NULL;
1267 g_return_val_if_fail( cache != NULL, NULL );
1270 gchar *uid = ADDRITEM_ID(folder);
1271 if( uid == NULL || *uid == '\0' ) return NULL;
1272 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1274 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1275 if( ! parent ) parent = cache->rootFolder;
1278 while( folder->listGroup ) {
1279 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1280 item = addrcache_remove_group( cache, item );
1282 addritem_free_item_group( item );
1287 while( folder->listPerson ) {
1288 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1289 item = addrcache_remove_person( cache, item );
1291 addritem_free_item_person( item );
1296 /* Recursive deletion of folder */
1297 while( folder->listFolder ) {
1298 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1299 item = addrcache_remove_folder_delete( cache, item );
1301 addritem_free_item_folder( item );
1306 /* Remove folder from parent's list and hash table */
1307 parent->listFolder = g_list_remove( parent->listFolder, folder );
1308 ADDRITEM_PARENT(folder) = NULL;
1309 g_hash_table_remove( cache->itemHash, uid );
1310 cache->dirtyFlag = TRUE;
1318 * Add person and address data to cache.
1319 * Enter: cache Cache.
1320 * folder Folder where to add person, or NULL for root folder.
1322 * address EMail address.
1324 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1325 * this will destroy the address book data.
1327 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1328 const gchar *address, const gchar *remarks )
1330 ItemPerson *person = NULL;
1331 ItemEMail *email = NULL;
1332 ItemFolder *f = folder;
1334 g_return_val_if_fail( cache != NULL, NULL );
1336 if( ! f ) f = cache->rootFolder;
1338 /* Create person object */
1339 person = addritem_create_item_person();
1340 addritem_person_set_common_name( person, name );
1341 addrcache_id_person( cache, person );
1342 addrcache_folder_add_person( cache, f, person );
1344 /* Create email object */
1345 email = addritem_create_item_email();
1346 addritem_email_set_address( email, address );
1347 addritem_email_set_remarks( email, remarks );
1348 addrcache_id_email( cache, email );
1349 addritem_person_add_email( person, email );
1350 cache->dirtyFlag = TRUE;