2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001 Match Grun
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * Functions to maintain address cache.
28 // #include "mgutils.h"
30 #include "addrcache.h"
32 #define ID_TIME_OFFSET 998000000
33 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
36 * Create new address cache.
38 AddressCache *addrcache_create() {
42 cache = g_new0( AddressCache, 1 );
43 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
45 cache->dataRead = FALSE;
46 cache->modified = FALSE;
47 cache->modifyTime = 0;
49 // Generate the next ID using system time
53 cache->nextID = t - ID_TIME_OFFSET;
56 cache->tempList = NULL;
57 cache->rootFolder = addritem_create_item_folder();
58 cache->rootFolder->isRoot = TRUE;
59 ADDRITEM_PARENT(cache->rootFolder) = NULL;
66 ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
67 g_return_if_fail( cache != NULL );
68 return cache->rootFolder;
70 GList *addrcache_get_list_folder( AddressCache *cache ) {
71 g_return_if_fail( cache != NULL );
72 return cache->rootFolder->listFolder;
74 GList *addrcache_get_list_person( AddressCache *cache ) {
75 g_return_if_fail( cache != NULL );
76 return cache->rootFolder->listPerson;
82 void addrcache_next_id( AddressCache *cache ) {
83 g_return_if_fail( cache != NULL );
88 * Refresh internal variables. This can be used force a reload.
90 void addrcache_refresh( AddressCache *cache ) {
91 cache->dataRead = FALSE;
92 cache->modified = TRUE;
93 cache->modifyTime = 0;
97 * Free hash table visitor function.
99 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
100 AddrItemObject *obj = ( AddrItemObject * ) value;
101 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
102 addritem_free_item_person( ( ItemPerson * ) obj );
104 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
105 addritem_free_item_group( ( ItemGroup * ) obj );
107 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
108 addritem_free_item_folder( ( ItemFolder * ) obj );
116 * Free hash table of address cache items.
118 static void addrcache_free_item_hash( GHashTable *table ) {
119 g_return_if_fail( table != NULL );
120 g_hash_table_freeze( table );
121 g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
122 g_hash_table_thaw( table );
123 g_hash_table_destroy( table );
127 * Free up folders and groups.
129 static void addrcache_free_all_folders( ItemFolder *parent ) {
130 GList *node = parent->listFolder;
132 ItemFolder *folder = node->data;
133 addrcache_free_all_folders( folder );
134 node = g_list_next( node );
136 g_list_free( parent->listPerson );
137 g_list_free( parent->listGroup );
138 g_list_free( parent->listFolder );
139 parent->listPerson = NULL;
140 parent->listGroup = NULL;
141 parent->listFolder = NULL;
145 * Clear the address cache.
147 void addrcache_clear( AddressCache *cache ) {
148 g_return_if_fail( cache != NULL );
150 // Free up folders and hash table
151 addrcache_free_all_folders( cache->rootFolder );
152 addrcache_free_item_hash( cache->itemHash );
153 cache->itemHash = NULL;
154 ADDRITEM_PARENT(cache->rootFolder) = NULL;
155 addritem_free_item_folder( cache->rootFolder );
156 cache->rootFolder = NULL;
157 g_list_free( cache->tempList );
158 cache->tempList = NULL;
160 // Reset to initial state
161 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
162 cache->rootFolder = addritem_create_item_folder();
163 cache->rootFolder->isRoot = TRUE;
164 ADDRITEM_PARENT(cache->rootFolder) = NULL;
166 addrcache_refresh( cache );
171 * Free address cache.
173 void addrcache_free( AddressCache *cache ) {
174 g_return_if_fail( cache != NULL );
176 addrcache_free_all_folders( cache->rootFolder );
177 addrcache_free_item_hash( cache->itemHash );
178 cache->itemHash = NULL;
179 ADDRITEM_PARENT(cache->rootFolder) = NULL;
180 addritem_free_item_folder( cache->rootFolder );
181 cache->rootFolder = NULL;
182 g_list_free( cache->tempList );
183 cache->tempList = NULL;
188 * Check whether file has changed by comparing with cache.
189 * return: TRUE if file has changed.
191 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
193 struct stat filestat;
196 if( 0 == lstat( path, &filestat ) ) {
197 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
204 * Save file time to cache.
205 * return: TRUE if time marked.
207 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
208 gboolean retVal = FALSE;
209 struct stat filestat;
211 if( 0 == lstat( path, &filestat ) ) {
212 cache->modifyTime = filestat.st_mtime;
220 * Print list of items.
222 void addrcache_print_item_list( GList *list, FILE *stream ) {
225 AddrItemObject *obj = node->data;
226 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
227 addritem_print_item_person( ( ItemPerson * ) obj, stream );
229 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
230 addritem_print_item_group( ( ItemGroup * ) obj, stream );
232 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
233 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
235 node = g_list_next( node );
237 fprintf( stream, "\t---\n" );
241 * Print item hash table visitor function.
243 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
244 AddrItemObject *obj = ( AddrItemObject * ) value;
245 FILE *stream = ( FILE * ) data;
246 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
247 addritem_print_item_person( ( ItemPerson * ) obj, stream );
249 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
250 addritem_print_item_group( ( ItemGroup * ) obj, stream );
252 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
253 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
258 * Dump entire address cache hash table contents.
260 void addrcache_print( AddressCache *cache, FILE *stream ) {
261 g_return_if_fail( cache != NULL );
262 fprintf( stream, "AddressCache:\n" );
263 fprintf( stream, "next id : %d\n", cache->nextID );
264 fprintf( stream, "mod time : %d\n", cache->modifyTime );
265 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
266 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
270 * Dump entire address cache hash table contents.
272 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
273 g_return_if_fail( cache != NULL );
274 addrcache_print( cache, stream );
275 g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
279 * Allocate ID for person.
281 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
282 g_return_if_fail( cache != NULL );
283 g_return_if_fail( person != NULL );
284 if( ADDRITEM_ID(person) ) return;
285 addrcache_next_id( cache );
286 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
290 * Allocate ID for group.
292 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
293 g_return_if_fail( cache != NULL );
294 g_return_if_fail( group != NULL );
295 if( ADDRITEM_ID(group) ) return;
296 addrcache_next_id( cache );
297 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
301 * Allocate ID for folder.
303 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
304 g_return_if_fail( cache != NULL );
305 g_return_if_fail( folder != NULL );
306 if( ADDRITEM_ID(folder) ) return;
307 addrcache_next_id( cache );
308 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
312 * Allocate ID for email address.
314 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
315 g_return_if_fail( cache != NULL );
316 g_return_if_fail( email != NULL );
317 if( ADDRITEM_ID(email) ) return;
318 addrcache_next_id( cache );
319 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
323 * Allocate ID for user attribute.
325 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
326 g_return_if_fail( cache != NULL );
327 g_return_if_fail( attrib != NULL );
328 if( attrib->uid ) return;
329 addrcache_next_id( cache );
330 attrib->uid = g_strdup_printf( "%d", cache->nextID );
334 * Add person to hash table.
335 * return: TRUE if item added.
337 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
338 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
341 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
346 * Add group to hash table.
347 * return: TRUE if item added.
349 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
350 g_return_if_fail( cache != NULL );
351 g_return_if_fail( group != NULL );
352 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
355 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
360 * Add folder to hash table.
361 * return: TRUE if item added.
363 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
364 g_return_if_fail( cache != NULL );
365 g_return_if_fail( folder != NULL );
366 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
369 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
374 * Add person to specified folder in cache.
376 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
377 gboolean retVal = FALSE;
378 g_return_if_fail( cache != NULL );
379 g_return_if_fail( folder != NULL );
380 g_return_if_fail( item != NULL );
381 retVal = addrcache_hash_add_person( cache, item );
383 addritem_folder_add_person( folder, item );
389 * Add folder to specified folder in cache.
391 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
392 gboolean retVal = FALSE;
393 g_return_if_fail( cache != NULL );
394 g_return_if_fail( folder != NULL );
395 g_return_if_fail( item != NULL );
396 retVal = addrcache_hash_add_folder( cache, item );
398 addritem_folder_add_folder( folder, item );
404 * Add folder to specified folder in cache.
406 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
407 gboolean retVal = FALSE;
408 g_return_if_fail( cache != NULL );
409 g_return_if_fail( folder != NULL );
410 g_return_if_fail( item != NULL );
411 retVal = addrcache_hash_add_group( cache, item );
413 addritem_folder_add_group( folder, item );
419 * Add person to address cache.
420 * return: TRUE if item added.
422 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
423 gboolean retVal = FALSE;
424 g_return_if_fail( cache != NULL );
425 g_return_if_fail( person != NULL );
426 retVal = addrcache_hash_add_person( cache, person );
428 addritem_folder_add_person( cache->rootFolder, person );
434 * Add EMail address to person.
435 * return: TRUE if item added.
437 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
438 g_return_if_fail( cache != NULL );
439 g_return_if_fail( person != NULL );
440 g_return_if_fail( email != NULL );
441 addritem_person_add_email( person, email );
446 * Add group to address cache.
447 * return: TRUE if item added.
449 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
450 gboolean retVal = FALSE;
451 g_return_if_fail( cache != NULL );
452 g_return_if_fail( group != NULL );
453 retVal = addrcache_hash_add_group( cache, group );
455 addritem_folder_add_group( cache->rootFolder, group );
461 * Add EMail address to person.
462 * return: TRUE if item added.
464 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
465 g_return_if_fail( cache != NULL );
466 g_return_if_fail( group != NULL );
467 g_return_if_fail( email != NULL );
468 addritem_group_add_email( group, email );
473 * Add folder to address cache.
474 * return: TRUE if item added.
476 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
477 gboolean retVal = FALSE;
478 g_return_if_fail( cache != NULL );
479 g_return_if_fail( folder != NULL );
480 retVal = addrcache_hash_add_folder( cache, folder );
482 addritem_folder_add_folder( cache->rootFolder, folder );
488 * Return pointer to object (either person or group) for specified ID.
489 * param: uid Object ID.
490 * return: Object, or NULL if not found.
492 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
493 AddrItemObject *obj = NULL;
496 g_return_if_fail( cache != NULL );
497 if( uid == NULL || *uid == '\0' ) return NULL;
498 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
500 // Check for matching UID
501 uidH = ADDRITEM_ID(obj);
503 if( strcmp( uidH, uid ) == 0 ) return obj;
510 * Return pointer for specified object ID.
511 * param: uid Object ID.
512 * return: Person object, or NULL if not found.
514 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
515 ItemPerson *person = NULL;
516 AddrItemObject *obj = addrcache_get_object( cache, uid );
518 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
519 person = ( ItemPerson * ) obj;
526 * Return pointer for specified object ID.
527 * param: uid group ID.
528 * return: Group object, or NULL if not found.
530 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
531 ItemGroup *group = NULL;
532 AddrItemObject *obj = addrcache_get_object( cache, uid );
534 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
535 group = ( ItemGroup * ) obj;
542 * Find email address in address cache.
543 * param: uid Object ID for person.
545 * return: email object for specified object ID and email ID, or NULL if not found.
547 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *uid, const gchar *eid ) {
548 AddrItemObject *objP;
549 if( eid == NULL || *eid == '\0' ) return NULL;
551 objP = addrcache_get_object( cache, uid );
553 if( ADDRITEM_TYPE(objP) == ITEMTYPE_PERSON ) {
554 // Sequential search through email addresses
555 ItemPerson *person = ( ItemPerson * ) objP;
556 GList *nodeMail = person->listEMail;
558 AddrItemObject *objE = nodeMail->data;
559 gchar *ide = ADDRITEM_ID(objE);
561 if( strcmp( ide, eid ) == 0 ) {
562 return ( ItemEMail * ) objE;
565 nodeMail = g_list_next( nodeMail );
573 * Remove attribute from person.
574 * param: uid Object ID for person.
576 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
578 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
579 UserAttribute *attrib = NULL;
581 if( aid == NULL || *aid == '\0' ) return NULL;
583 person = addrcache_get_person( cache, uid );
585 attrib = addritem_person_remove_attrib_id( person, aid );
591 * Remove attribute from person.
592 * param: person Person.
593 * attrib Attribute to remove.
594 * return: UserAttribute object. Note that object should still be freed.
596 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
597 UserAttribute *found = NULL;
598 g_return_if_fail( cache != NULL );
599 if( person && attrib ) {
600 found = addritem_person_remove_attribute( person, attrib );
606 * Remove group from address cache for specified ID.
607 * param: uid Object ID.
608 * return: Group, or NULL if not found. Note that object should still be freed.
610 ItemGroup *addrcache_remove_group_id( AddressCache *cache, const gchar *uid ) {
611 AddrItemObject *obj = NULL;
613 g_return_if_fail( cache != NULL );
614 if( uid == NULL || *uid == '\0' ) return NULL;
615 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
617 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
618 ItemGroup *group = ( ItemGroup * ) obj;
619 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
620 if( ! parent ) parent = cache->rootFolder;
621 // Remove group from parent's list and hash table
622 parent->listGroup = g_list_remove( parent->listGroup, group );
623 g_hash_table_remove( cache->itemHash, uid );
624 return ( ItemGroup * ) obj;
631 * Remove group from address cache.
632 * param: group Group to remove.
633 * return: Group, or NULL if not found. Note that object should still be freed.
635 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
636 AddrItemObject *obj = NULL;
638 g_return_if_fail( cache != NULL );
640 gchar *uid = ADDRITEM_ID(group);
641 if( uid == NULL || *uid == '\0' ) return NULL;
642 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
644 ItemGroup *item = ( ItemGroup * ) obj;
645 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
646 if( ! parent ) parent = cache->rootFolder;
648 // Remove group from parent's list and hash table
649 parent->listGroup = g_list_remove( parent->listGroup, obj );
650 g_hash_table_remove( cache->itemHash, uid );
658 * Remove person's email address from all groups in folder.
660 static void addrcache_foldergrp_rem_person( ItemFolder *folder, ItemPerson *person ) {
661 GList *nodeGrp = folder->listGroup;
663 ItemGroup *group = nodeGrp->data;
665 // Remove each email address that belongs to the person from the list
666 GList *node = person->listEMail;
668 group->listEMail = g_list_remove( group->listEMail, node->data );
669 node = g_list_next( node );
672 nodeGrp = g_list_next( nodeGrp );
677 * Remove person from address cache for specified ID. Note that person still retains
678 * their EMail addresses. Also, links to these email addresses will be severed from
680 * param: uid Object ID.
681 * return: Person, or NULL if not found. Note that object should still be freed.
683 ItemPerson *addrcache_remove_person_id( AddressCache *cache, const gchar *uid ) {
684 AddrItemObject *obj = NULL;
686 g_return_if_fail( cache != NULL );
687 if( uid == NULL || *uid == '\0' ) return NULL;
688 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
690 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
691 // Remove person's email addresses from all groups where
692 // referenced and from hash table.
693 ItemPerson *person = ( ItemPerson * ) obj;
694 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
695 if( ! parent ) parent = cache->rootFolder;
696 // Remove emails from groups, remove from parent's list
698 addrcache_foldergrp_rem_person( parent, person );
699 parent->listPerson = g_list_remove( parent->listPerson, person );
700 g_hash_table_remove( cache->itemHash, uid );
708 * Remove specified person from address cache.
709 * param: person Person to remove.
710 * return: Person, or NULL if not found. Note that object should still be freed.
712 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
713 AddrItemObject *obj = NULL;
715 g_return_if_fail( cache != NULL );
717 gchar *uid = ADDRITEM_ID(person);
718 if( uid == NULL || *uid == '\0' ) return NULL;
719 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
721 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
722 // Remove person's email addresses from all groups where
723 // referenced and from hash table.
724 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
725 if( ! parent ) parent = cache->rootFolder;
726 addrcache_foldergrp_rem_person( parent, person );
727 parent->listPerson = g_list_remove( parent->listPerson, person );
728 g_hash_table_remove( cache->itemHash, uid );
737 * Remove email from group item hash table visitor function.
739 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
740 AddrItemObject *obj = ( AddrItemObject * ) value;
741 ItemEMail *email = ( ItemEMail * ) data;
742 if( ! email ) return;
743 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
744 ItemGroup *group = ( ItemGroup * ) value;
746 // Remove each email address that belongs to the person from the list
747 group->listEMail = g_list_remove( group->listEMail, email );
753 * Remove email address in address cache for specified ID.
754 * param: uid Object ID for person.
756 * return: EMail object, or NULL if not found. Note that object should still be freed.
758 ItemEMail *addrcache_person_remove_email_id( AddressCache *cache, const gchar *uid, const gchar *eid ) {
759 ItemEMail *email = NULL;
761 if( eid == NULL || *eid == '\0' ) return NULL;
763 person = addrcache_get_person( cache, uid );
765 email = addritem_person_remove_email_id( person, eid );
767 // Remove email from all groups.
768 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
770 // Remove email from person's address list
771 if( person->listEMail ) {
772 person->listEMail = g_list_remove( person->listEMail, email );
774 // Unlink reference to person.
775 ADDRITEM_PARENT(email) = NULL;
782 * Remove email address in address cache for specified person.
783 * param: person Person.
784 * email EMail to remove.
785 * return: EMail object, or NULL if not found. Note that object should still be freed.
787 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
788 ItemEMail *found = NULL;
789 g_return_if_fail( cache != NULL );
790 if( person && email ) {
791 found = addritem_person_remove_email( person, email );
793 // Remove email from all groups.
794 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
796 // Remove email from person's address list
797 if( person->listEMail ) {
798 person->listEMail = g_list_remove( person->listEMail, email );
800 // Unlink reference to person.
801 ADDRITEM_PARENT(email) = NULL;
808 * Return link list of address items for root level folder. Note that the list contains
809 * references to items and should be g_free() when done. Do *NOT* attempt to use the
810 * addrcache_free_xxx() functions... this will destroy the address cache data!
811 * Return: List of items, or NULL if none.
813 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
816 ItemFolder *f = folder;
817 g_return_if_fail( cache != NULL );
819 if( ! f ) f = cache->rootFolder;
820 node = f->listPerson;
822 list = g_list_append( list, node->data );
823 node = g_list_next( node );
827 list = g_list_append( list, node->data );
828 node = g_list_next( node );
834 * Return link list of persons for specified folder. Note that the list contains
835 * references to items and should be g_free() when done. Do *NOT* attempt to use the
836 * addrcache_free_xxx() functions... this will destroy the address cache data!
837 * Return: List of items, or NULL if none.
839 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
842 ItemFolder *f = folder;
843 g_return_if_fail( cache != NULL );
845 if( ! f ) f = cache->rootFolder;
846 return addritem_folder_get_person_list( f );
850 * Return link list of group items for specified folder. Note that the list contains
851 * references to items and should be g_free() when done. Do *NOT* attempt to use the
852 * addrcache_free_xxx() functions... this will destroy the address cache data!
853 * Return: List of items, or NULL if none.
855 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
858 ItemFolder *f = folder;
859 g_return_if_fail( cache != NULL );
860 if( ! f ) f = cache->rootFolder;
861 return addritem_folder_get_group_list( f );
865 * Return link list of folder items for specified folder. Note that the list contains
866 * references to items and should be g_free() when done. Do *NOT* attempt to used the
867 * addrcache_free_xxx() functions... this will destroy the address cache data!
868 * Return: List of items, or NULL if none.
870 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
873 ItemFolder *f = folder;
874 g_return_if_fail( cache != NULL );
875 if( ! f ) f = cache->rootFolder;
876 node = f->listFolder;
878 list = g_list_append( list, node->data );
879 node = g_list_next( node );
885 * Return link list of address items for root level folder. Note that the list contains
886 * references to items and should be g_free() when done. Do *NOT* attempt to used the
887 * addrcache_free_xxx() functions... this will destroy the address cache data!
888 * Return: List of items, or NULL if none.
890 GList *addrcache_get_address_list( AddressCache *cache ) {
892 g_return_if_fail( cache != NULL );
893 return addrcache_folder_get_address_list( cache, cache->rootFolder );
897 * Return link list of persons for root level folder. Note that the list contains
898 * references to items and should be g_free() when done. Do *NOT* attempt to used the
899 * addrcache_free_xxx() functions... this will destroy the address cache data!
900 * Return: List of items, or NULL if none.
902 GList *addrcache_get_person_list( AddressCache *cache ) {
903 g_return_if_fail( cache != NULL );
904 return addritem_folder_get_person_list( cache->rootFolder );
908 * Return link list of group items in root level folder. Note that the list contains
909 * references to items and should be g_free() when done. Do *NOT* attempt to used the
910 * addrcache_free_xxx() functions... this will destroy the address cache data!
911 * Return: List of items, or NULL if none.
913 GList *addrcache_get_group_list( AddressCache *cache ) {
914 g_return_if_fail( cache != NULL );
915 return cache->rootFolder->listGroup;
919 * Return link list of folder items in root level folder. Note that the list contains
920 * references to items and should be g_free() when done. Do *NOT* attempt to used the
921 * addrcache_free_xxx() functions... this will destroy the address cache data!
922 * Return: List of items, or NULL if none.
924 GList *addrcache_get_folder_list( AddressCache *cache ) {
925 g_return_if_fail( cache != NULL );
926 return cache->rootFolder->listFolder;
930 * Group visitor function.
932 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
933 AddrItemObject *obj = ( AddrItemObject * ) value;
934 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
935 AddressCache *cache = data;
936 ItemGroup *group = ( ItemGroup * ) obj;
937 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
938 GList *node = group->listEMail;
940 ItemEMail *email = ( ItemEMail * ) node->data;
941 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
942 if( ! g_list_find( cache->tempList, group ) ) {
943 cache->tempList = g_list_append( cache->tempList, group );
946 node = g_list_next( node );
952 * Return link list of groups which contain a reference to specified person's email
955 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
957 g_return_if_fail( cache != NULL );
958 cache->tempList = NULL;
959 cache->tempList = g_list_append( cache->tempList, person );
960 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
961 cache->tempList = g_list_remove( cache->tempList, person );
962 list = cache->tempList;
963 cache->tempList = NULL;
968 * Find root folder for specified folder.
969 * Enter: folder Folder to search.
970 * Return: root folder, or NULL if not found.
972 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
973 ItemFolder *item = folder;
976 if( item->isRoot ) break;
977 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
981 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
987 * Get all person visitor function.
989 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
990 AddrItemObject *obj = ( AddrItemObject * ) value;
991 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
992 AddressCache *cache = data;
993 cache->tempList = g_list_append( cache->tempList, obj );
998 * Return link list of all persons in address cache. Note that the list contains
999 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1000 * this will destroy the address cache data!
1001 * Return: List of items, or NULL if none.
1003 GList *addrcache_get_all_persons( AddressCache *cache ) {
1005 g_return_if_fail( cache != NULL );
1007 cache->tempList = NULL;
1008 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1009 list = cache->tempList;
1010 cache->tempList = NULL;
1015 * Remove folder from cache. Children are re-parented to parent folder.
1016 * param: folder Folder to remove.
1017 * return: Folder, or NULL if not found. Note that object should still be freed.
1019 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1020 AddrItemObject *obj = NULL;
1022 g_return_if_fail( cache != NULL );
1024 gchar *uid = ADDRITEM_ID(folder);
1025 if( uid == NULL || *uid == '\0' ) return NULL;
1026 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1028 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1030 AddrItemObject *aio;
1031 if( ! parent ) parent = cache->rootFolder;
1033 // Re-parent children in folder
1034 node = folder->listFolder;
1036 aio = ( AddrItemObject * ) node->data;
1037 parent->listFolder = g_list_append( parent->listFolder, aio );
1038 aio->parent = ADDRITEM_OBJECT(parent);
1039 node = g_list_next( node );
1041 node = folder->listPerson;
1043 aio = ( AddrItemObject * ) node->data;
1044 parent->listPerson = g_list_append( parent->listPerson, aio );
1045 aio->parent = ADDRITEM_OBJECT(parent);
1046 node = g_list_next( node );
1048 node = folder->listGroup;
1050 aio = ( AddrItemObject * ) node->data;
1051 parent->listGroup = g_list_append( parent->listGroup, aio );
1052 aio->parent = ADDRITEM_OBJECT(parent);
1053 node = g_list_next( node );
1056 // Remove folder from parent's list and hash table
1057 parent->listFolder = g_list_remove( parent->listFolder, folder );
1058 ADDRITEM_PARENT(folder) = NULL;
1059 g_hash_table_remove( cache->itemHash, uid );
1067 * Remove folder from cache. Children are deleted.
1068 * param: folder Folder to remove.
1069 * return: Folder, or NULL if not found. Note that object should still be freed.
1071 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1072 AddrItemObject *obj = NULL;
1074 g_return_if_fail( cache != NULL );
1076 gchar *uid = ADDRITEM_ID(folder);
1077 if( uid == NULL || *uid == '\0' ) return NULL;
1078 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1080 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1082 AddrItemObject *aio;
1083 if( ! parent ) parent = cache->rootFolder;
1086 while( folder->listGroup ) {
1087 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1088 item = addrcache_remove_group( cache, item );
1090 addritem_free_item_group( item );
1095 while( folder->listPerson ) {
1096 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1097 item = addrcache_remove_person( cache, item );
1099 addritem_free_item_person( item );
1104 // Recursive deletion of folder
1105 while( folder->listFolder ) {
1106 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1107 item = addrcache_remove_folder_delete( cache, item );
1109 addritem_free_item_folder( item );
1114 // Remove folder from parent's list and hash table
1115 parent->listFolder = g_list_remove( parent->listFolder, folder );
1116 ADDRITEM_PARENT(folder) = NULL;
1117 g_hash_table_remove( cache->itemHash, uid );
1125 * Add person and address data to cache.
1126 * Enter: cache Cache.
1127 * folder Folder where to add person, or NULL for root folder.
1129 * address EMail address.
1131 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1132 * this will destroy the address book data.
1134 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1135 const gchar *address, const gchar *remarks )
1137 ItemPerson *person = NULL;
1138 ItemEMail *email = NULL;
1139 ItemFolder *f = folder;
1141 g_return_if_fail( cache != NULL );
1143 if( ! f ) f = cache->rootFolder;
1145 // Create person object
1146 person = addritem_create_item_person();
1147 addritem_person_set_common_name( person, name );
1148 addrcache_id_person( cache, person );
1149 addrcache_folder_add_person( cache, f, person );
1151 // Create email object
1152 email = addritem_create_item_email();
1153 addritem_email_set_address( email, address );
1154 addritem_email_set_remarks( email, remarks );
1155 addrcache_id_email( cache, email );
1156 addritem_person_add_email( person, email );