Sync Spanish manual
[claws.git] / src / addrcache.c
blobd8049feea6e13832456f27d5e60e1c15af25d9f4
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2012 Match Grun and the Claws Mail team
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 3 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, see <http://www.gnu.org/licenses/>.
21 * Functions to maintain address cache.
24 #include "config.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
30 #include "mgutils.h"
31 #include "addrcache.h"
32 #include "utils.h"
34 #define ID_TIME_OFFSET 998000000
35 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
37 static int _nextCacheID__ = 0;
40 * Generate next cache ID.
42 static int addrcache_next_cache_id() {
43 int retVal;
45 if( _nextCacheID__ == 0 ) {
46 _nextCacheID__ = 1;
48 retVal = _nextCacheID__;
49 ++_nextCacheID__;
50 return retVal;
54 * Create new address cache.
56 AddressCache *addrcache_create() {
57 AddressCache *cache;
58 gint t;
60 cache = g_new0( AddressCache, 1 );
61 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
62 cache->cacheID = g_strdup_printf( "%d", addrcache_next_cache_id() );
64 cache->dataRead = FALSE;
65 cache->modified = FALSE;
66 cache->dirtyFlag = FALSE;
67 cache->accessFlag = FALSE;
68 cache->name = NULL;
69 cache->modifyTime = 0;
71 /* Generate the next ID using system time */
72 cache->nextID = 1;
73 t = time( NULL );
74 if( t > 0 ) {
75 cache->nextID = t - ID_TIME_OFFSET;
78 cache->tempList = NULL;
79 cache->rootFolder = addritem_create_item_folder();
80 cache->rootFolder->isRoot = TRUE;
81 ADDRITEM_PARENT(cache->rootFolder) = NULL;
82 return cache;
86 * Properties.
88 ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
89 cm_return_val_if_fail( cache != NULL, NULL );
90 return cache->rootFolder;
92 GList *addrcache_get_list_folder( AddressCache *cache ) {
93 cm_return_val_if_fail( cache != NULL, NULL );
94 return cache->rootFolder->listFolder;
96 GList *addrcache_get_list_person( AddressCache *cache ) {
97 cm_return_val_if_fail( cache != NULL, NULL );
98 return cache->rootFolder->listPerson;
100 gboolean addrcache_get_dirty( AddressCache *cache ) {
101 cm_return_val_if_fail( cache != NULL, FALSE );
102 return cache->dirtyFlag;
104 void addrcache_set_dirty( AddressCache *cache, const gboolean value ) {
105 cm_return_if_fail( cache != NULL );
106 cache->dirtyFlag = value;
108 gchar *addrcache_get_name( AddressCache *cache ) {
109 cm_return_val_if_fail( cache != NULL, NULL );
110 return cache->name;
112 void addrcache_set_name( AddressCache *cache, const gchar *value ) {
113 cm_return_if_fail( cache != NULL );
114 cache->name = mgu_replace_string( cache->name, value );
115 g_strstrip( cache->name );
116 cache->dirtyFlag = TRUE;
120 * Generate next ID.
122 static void addrcache_next_id( AddressCache *cache ) {
123 cm_return_if_fail( cache != NULL );
124 cache->nextID++;
128 * Refresh internal variables. This can be used force a reload.
130 void addrcache_refresh( AddressCache *cache ) {
131 cache->dataRead = FALSE;
132 cache->modified = TRUE;
133 cache->accessFlag = FALSE;
134 cache->modifyTime = 0;
138 * Free hash table visitor function.
140 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
141 AddrItemObject *obj = ( AddrItemObject * ) value;
143 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
144 addritem_free_item_person( ( ItemPerson * ) obj );
146 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
147 addritem_free_item_email( ( ItemEMail * ) obj );
149 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
150 addritem_free_item_group( ( ItemGroup * ) obj );
152 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
153 addritem_free_item_folder( ( ItemFolder * ) obj );
155 key = NULL;
156 value = NULL;
157 return TRUE;
161 * Free hash table of address cache items.
163 static void addrcache_free_item_hash( GHashTable *table ) {
164 cm_return_if_fail( table != NULL );
165 g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
169 * Free up folders and groups.
171 static void addrcache_free_all_folders( ItemFolder *parent ) {
172 GList *node;
174 if( parent == NULL ) return;
176 node = parent->listFolder;
177 while( node ) {
178 ItemFolder *folder = node->data;
179 addrcache_free_all_folders( folder );
180 node->data = NULL;
181 node = g_list_next( node );
183 g_list_free( parent->listPerson );
184 g_list_free( parent->listGroup );
185 g_list_free( parent->listFolder );
186 parent->listPerson = NULL;
187 parent->listGroup = NULL;
188 parent->listFolder = NULL;
192 * Clear the address cache.
194 void addrcache_clear( AddressCache *cache ) {
195 cm_return_if_fail( cache != NULL );
197 /* g_print( "...addrcache_clear :%s:\n", cache->name ); */
198 /* Free up folders and hash table */
199 addrcache_free_all_folders( cache->rootFolder );
200 addrcache_free_item_hash( cache->itemHash );
201 g_hash_table_destroy( cache->itemHash );
202 cache->itemHash = NULL;
203 ADDRITEM_PARENT(cache->rootFolder) = NULL;
204 addritem_free_item_folder( cache->rootFolder );
205 cache->rootFolder = NULL;
206 if( cache->tempList ) g_list_free( cache->tempList );
207 cache->tempList = NULL;
209 /* Reset to initial state */
210 cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
211 cache->rootFolder = addritem_create_item_folder();
212 cache->rootFolder->isRoot = TRUE;
213 ADDRITEM_PARENT(cache->rootFolder) = NULL;
215 addrcache_refresh( cache );
219 * Free address cache.
221 void addrcache_free( AddressCache *cache ) {
222 cm_return_if_fail( cache != NULL );
224 cache->dirtyFlag = FALSE;
225 addrcache_free_all_folders( cache->rootFolder );
226 addrcache_free_item_hash( cache->itemHash );
227 g_hash_table_destroy( cache->itemHash );
228 cache->itemHash = NULL;
229 ADDRITEM_PARENT(cache->rootFolder) = NULL;
230 addritem_free_item_folder( cache->rootFolder );
231 cache->rootFolder = NULL;
232 g_list_free( cache->tempList );
233 cache->tempList = NULL;
234 g_free( cache->cacheID );
235 cache->cacheID = NULL;
236 g_free( cache->name );
237 cache->name = NULL;
238 g_free( cache );
242 * Check whether file has changed by comparing with cache.
243 * return: TRUE if file has changed.
245 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
246 gboolean retVal;
247 GStatBuf filestat;
248 retVal = TRUE;
249 if( path ) {
250 if( 0 == g_stat( path, &filestat ) ) {
251 if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
254 return retVal;
258 * Save file time to cache.
259 * return: TRUE if time marked.
261 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
262 gboolean retVal = FALSE;
263 GStatBuf filestat;
264 if( path ) {
265 if( 0 == g_stat( path, &filestat ) ) {
266 cache->modifyTime = filestat.st_mtime;
267 retVal = TRUE;
270 return retVal;
274 * Dump entire address cache hash table contents.
276 void addrcache_print( AddressCache *cache, FILE *stream ) {
277 cm_return_if_fail( cache != NULL );
278 fprintf( stream, "AddressCache:\n" );
279 fprintf( stream, "cache id : %s\n", cache->cacheID );
280 fprintf( stream, "next id : %d\n", cache->nextID );
281 fprintf( stream, "name : %s\n", cache->name );
282 fprintf( stream, "mod time : %ld\n", (long int)cache->modifyTime );
283 fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
284 fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
288 * Allocate ID for person.
290 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
291 cm_return_if_fail( cache != NULL );
292 cm_return_if_fail( person != NULL );
293 if( ADDRITEM_ID(person) ) return;
294 addrcache_next_id( cache );
295 ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
299 * Allocate ID for group.
301 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
302 cm_return_if_fail( cache != NULL );
303 cm_return_if_fail( group != NULL );
304 if( ADDRITEM_ID(group) ) return;
305 addrcache_next_id( cache );
306 ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
310 * Allocate ID for folder.
312 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
313 cm_return_if_fail( cache != NULL );
314 cm_return_if_fail( folder != NULL );
315 if( ADDRITEM_ID(folder) ) return;
316 addrcache_next_id( cache );
317 ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
321 * Allocate ID for email address.
323 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
324 cm_return_if_fail( cache != NULL );
325 cm_return_if_fail( email != NULL );
326 if( ADDRITEM_ID(email) ) return;
327 addrcache_next_id( cache );
328 ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
332 * Allocate ID for user attribute.
334 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
335 cm_return_if_fail( cache != NULL );
336 cm_return_if_fail( attrib != NULL );
337 if( attrib->uid ) return;
338 addrcache_next_id( cache );
339 attrib->uid = g_strdup_printf( "%d", cache->nextID );
343 * Add person to hash table.
344 * return: TRUE if item added.
346 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
347 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
348 return FALSE;
350 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
351 return TRUE;
355 * Add email to hash table.
356 * return: TRUE if item added.
358 static gboolean addrcache_hash_add_email( AddressCache *cache, ItemEMail *email ) {
359 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(email) ) ) {
360 return FALSE;
362 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(email), email );
363 return TRUE;
367 * Add group to hash table.
368 * return: TRUE if item added.
370 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
371 cm_return_val_if_fail( cache != NULL, FALSE );
372 cm_return_val_if_fail( group != NULL, FALSE );
374 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
375 return FALSE;
377 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
378 return TRUE;
382 * Add folder to hash table.
383 * return: TRUE if item added.
385 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
386 cm_return_val_if_fail( cache != NULL, FALSE );
387 cm_return_val_if_fail( folder != NULL, FALSE );
389 if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
390 return FALSE;
392 g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
393 return TRUE;
397 * Add person to specified folder in cache.
399 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
400 gboolean retVal = FALSE;
402 cm_return_val_if_fail( cache != NULL, FALSE );
403 cm_return_val_if_fail( folder != NULL, FALSE );
404 cm_return_val_if_fail( item != NULL, FALSE );
406 retVal = addrcache_hash_add_person( cache, item );
407 if( retVal ) {
408 addritem_folder_add_person( folder, item );
409 cache->dirtyFlag = TRUE;
411 return retVal;
415 * Add folder to specified folder in cache.
417 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
418 gboolean retVal = FALSE;
420 cm_return_val_if_fail( cache != NULL, FALSE );
421 cm_return_val_if_fail( folder != NULL, FALSE );
422 cm_return_val_if_fail( item != NULL, FALSE );
424 retVal = addrcache_hash_add_folder( cache, item );
425 if( retVal ) {
426 addritem_folder_add_folder( folder, item );
427 cache->dirtyFlag = TRUE;
429 return TRUE;
433 * Add folder to specified folder in cache.
435 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
436 gboolean retVal = FALSE;
438 cm_return_val_if_fail( cache != NULL, FALSE );
439 cm_return_val_if_fail( folder != NULL, FALSE );
440 cm_return_val_if_fail( item != NULL, FALSE );
442 retVal = addrcache_hash_add_group( cache, item );
443 if( retVal ) {
444 addritem_folder_add_group( folder, item );
445 cache->dirtyFlag = TRUE;
447 return retVal;
451 * Add person to address cache.
452 * return: TRUE if item added.
454 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
455 gboolean retVal = FALSE;
457 cm_return_val_if_fail( cache != NULL, FALSE );
458 cm_return_val_if_fail( person != NULL, FALSE );
460 retVal = addrcache_hash_add_person( cache, person );
461 if( retVal ) {
462 addritem_folder_add_person( cache->rootFolder, person );
463 cache->dirtyFlag = TRUE;
465 return retVal;
469 * Add EMail address to person.
470 * return: TRUE if item added.
472 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
473 gboolean retVal = FALSE;
475 cm_return_val_if_fail( cache != NULL, FALSE );
476 cm_return_val_if_fail( person != NULL, FALSE );
477 cm_return_val_if_fail( email != NULL, FALSE );
479 retVal = addrcache_hash_add_email( cache, email );
480 if( retVal ) {
481 addritem_person_add_email( person, email );
482 cache->dirtyFlag = TRUE;
484 return retVal;
488 * Add group to address cache.
489 * return: TRUE if item added.
491 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
492 gboolean retVal = FALSE;
494 cm_return_val_if_fail( cache != NULL, FALSE );
495 cm_return_val_if_fail( group != NULL, FALSE );
497 retVal = addrcache_hash_add_group( cache, group );
498 if( retVal ) {
499 addritem_folder_add_group( cache->rootFolder, group );
500 cache->dirtyFlag = TRUE;
502 return retVal;
506 * Add EMail address to person.
507 * return: TRUE if item added.
509 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
510 cm_return_val_if_fail( cache != NULL, FALSE );
511 cm_return_val_if_fail( group != NULL, FALSE );
512 cm_return_val_if_fail( email != NULL, FALSE );
514 addritem_group_add_email( group, email );
515 cache->dirtyFlag = TRUE;
516 return TRUE;
520 * Add folder to address cache.
521 * return: TRUE if item added.
523 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
524 gboolean retVal = FALSE;
526 cm_return_val_if_fail( cache != NULL, FALSE );
527 cm_return_val_if_fail( folder != NULL, FALSE );
529 retVal = addrcache_hash_add_folder( cache, folder );
530 if( retVal ) {
531 addritem_folder_add_folder( cache->rootFolder, folder );
532 cache->dirtyFlag = TRUE;
534 return retVal;
538 * Move person to destination folder.
539 * Enter: cache Cache.
540 * person Person to move.
541 * target Target folder.
543 void addrcache_folder_move_person(
544 AddressCache *cache, ItemPerson *person, ItemFolder *target )
546 ItemFolder *parent;
548 cm_return_if_fail( cache != NULL );
549 cm_return_if_fail( person != NULL );
551 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
552 if( ! parent ) parent = cache->rootFolder;
553 parent->listPerson = g_list_remove( parent->listPerson, person );
554 target->listPerson = g_list_append( target->listPerson, person );
555 ADDRITEM_PARENT(person) = ADDRITEM_OBJECT(target);
556 cache->dirtyFlag = TRUE;
560 * Move group to destination folder.
561 * Enter: cache Cache.
562 * group Group to move.
563 * target Target folder.
565 void addrcache_folder_move_group(
566 AddressCache *cache, ItemGroup *group, ItemFolder *target )
568 ItemFolder *parent;
570 cm_return_if_fail( cache != NULL );
571 cm_return_if_fail( group != NULL );
573 parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
574 if( ! parent ) parent = cache->rootFolder;
575 parent->listGroup = g_list_remove( parent->listGroup, group );
576 target->listGroup = g_list_append( target->listGroup, group );
577 ADDRITEM_PARENT(group) = ADDRITEM_OBJECT(target);
578 cache->dirtyFlag = TRUE;
582 * Move folder to destination folder.
583 * Enter: cache Cache.
584 * folder Folder to move.
585 * target Target folder.
587 void addrcache_folder_move_folder(
588 AddressCache *cache, ItemFolder *folder, ItemFolder *target )
590 ItemFolder *parent;
592 cm_return_if_fail( cache != NULL );
593 cm_return_if_fail( folder != NULL );
595 parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
596 if( ! parent ) parent = cache->rootFolder;
597 parent->listFolder = g_list_remove( parent->listFolder, folder );
598 target->listFolder = g_list_append( target->listFolder, folder );
599 ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(target);
600 cache->dirtyFlag = TRUE;
604 * Return pointer to object (either person or group) for specified ID.
605 * param: uid Object ID.
606 * return: Object, or NULL if not found.
608 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
609 AddrItemObject *obj = NULL;
610 gchar *uidH;
612 cm_return_val_if_fail( cache != NULL, NULL );
614 if( uid == NULL || *uid == '\0' ) return NULL;
615 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
616 if( obj ) {
617 /* Check for matching UID */
618 uidH = ADDRITEM_ID(obj);
619 if( uidH ) {
620 if( strcmp( uidH, uid ) == 0 ) return obj;
623 return NULL;
627 * Find email address in address cache.
628 * param: eid EMail ID.
629 * return: email object for specified object ID and email ID, or NULL if not found.
631 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *eid ) {
632 ItemEMail *email = NULL;
633 AddrItemObject *obj = addrcache_get_object( cache, eid );
635 if( obj ) {
636 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
637 email = ( ItemEMail * ) obj;
640 return email;
644 * Remove group from address cache.
645 * param: group Group to remove.
646 * return: Group, or NULL if not found. Note that object should still be freed.
648 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
649 AddrItemObject *obj = NULL;
651 cm_return_val_if_fail( cache != NULL, NULL );
653 if( group ) {
654 gchar *uid = ADDRITEM_ID(group);
655 if( uid == NULL || *uid == '\0' ) return NULL;
656 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
657 if( obj ) {
658 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
659 if( ! parent ) parent = cache->rootFolder;
661 /* Remove group from parent's list and hash table */
662 parent->listGroup = g_list_remove( parent->listGroup, obj );
663 g_hash_table_remove( cache->itemHash, uid );
664 cache->dirtyFlag = TRUE;
665 return group;
668 return NULL;
672 * Remove specified email from address cache. Note that object is only
673 * removed from cache and not parent objects.
674 * param: email EMail to remove.
675 * return: EMail, or NULL if not found. Note that object should still be freed.
677 ItemEMail *addrcache_remove_email( AddressCache *cache, ItemEMail *email ) {
678 AddrItemObject *obj = NULL;
680 cm_return_val_if_fail( cache != NULL, NULL );
682 if( email ) {
683 gchar *eid = ADDRITEM_ID(email);
684 if( eid == NULL || *eid == '\0' ) return NULL;
685 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, eid );
686 if( obj ) {
687 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
688 /* Remove email addresses from hash table. */
689 g_hash_table_remove( cache->itemHash, eid );
690 cache->dirtyFlag = TRUE;
691 return email;
695 return NULL;
699 * Hash table visitor function to remove email from group.
701 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
702 AddrItemObject *obj = ( AddrItemObject * ) value;
703 ItemEMail *email = ( ItemEMail * ) data;
705 if( ! email ) return;
706 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
707 ItemGroup *group = ( ItemGroup * ) value;
708 if( group ) {
709 /* Remove each email address that belongs to the person from the list */
710 group->listEMail = g_list_remove( group->listEMail, email );
716 * Remove specified person from address cache.
717 * param: person Person to remove.
718 * return: Person, or NULL if not found. Note that object should still be freed.
720 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
721 AddrItemObject *obj = NULL;
722 gchar *uid;
724 cm_return_val_if_fail( cache != NULL, NULL );
726 if( person ) {
727 uid = ADDRITEM_ID(person);
728 if( uid == NULL || *uid == '\0' ) return NULL;
729 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
730 if( obj ) {
731 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
732 ItemFolder *parent;
733 GList *node;
735 /* Remove all email addresses for person */
736 /* from groups and from hash table */
737 node = person->listEMail;
738 while( node ) {
739 ItemEMail *email;
740 gchar *eid;
742 email = node->data;
743 g_hash_table_foreach( cache->itemHash,
744 addrcache_allgrp_rem_email_vis, email );
745 eid = ADDRITEM_ID( email );
746 g_hash_table_remove( cache->itemHash, eid );
747 node = g_list_next( node );
750 /* Remove person from owning folder */
751 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
752 if( ! parent ) parent = cache->rootFolder;
753 parent->listPerson = g_list_remove( parent->listPerson, person );
754 g_hash_table_remove( cache->itemHash, uid );
755 cache->dirtyFlag = TRUE;
756 return person;
760 return NULL;
764 * Remove email address in address cache for specified person.
765 * param: person Person.
766 * email EMail to remove.
767 * return: EMail object, or NULL if not found. Note that object should still be freed.
769 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
770 ItemEMail *found = NULL;
772 cm_return_val_if_fail( cache != NULL, NULL );
774 if( person && email ) {
775 found = addritem_person_remove_email( person, email );
776 if( found ) {
777 /* Remove email from all groups. */
778 g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
780 /* Remove email from person's address list */
781 if( person->listEMail ) {
782 person->listEMail = g_list_remove( person->listEMail, email );
784 /* Unlink reference to person. */
785 ADDRITEM_PARENT(email) = NULL;
786 cache->dirtyFlag = TRUE;
789 return found;
793 * Group visitor function.
795 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
796 AddrItemObject *obj = ( AddrItemObject * ) value;
798 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
799 AddressCache *cache = data;
800 ItemGroup *group = ( ItemGroup * ) obj;
801 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
802 GList *node = group->listEMail;
803 while( node ) {
804 ItemEMail *email = ( ItemEMail * ) node->data;
805 if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
806 if( ! g_list_find( cache->tempList, group ) ) {
807 cache->tempList = g_list_append( cache->tempList, group );
810 node = g_list_next( node );
816 * Return linked list of groups which contain a reference to specified person's email
817 * address.
819 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
820 GList *list = NULL;
822 cm_return_val_if_fail( cache != NULL, NULL );
824 cache->tempList = NULL;
825 cache->tempList = g_list_append( cache->tempList, person );
826 g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
827 cache->tempList = g_list_remove( cache->tempList, person );
828 list = cache->tempList;
829 cache->tempList = NULL;
830 return list;
834 * Get all person visitor function.
836 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
837 AddrItemObject *obj = ( AddrItemObject * ) value;
839 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
840 AddressCache *cache = data;
841 cache->tempList = g_list_append( cache->tempList, obj );
846 * Return link list of all persons in address cache. Note that the list contains
847 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
848 * this will destroy the address cache data!
849 * Return: List of items, or NULL if none.
851 GList *addrcache_get_all_persons( AddressCache *cache ) {
852 GList *list = NULL;
854 cm_return_val_if_fail( cache != NULL, NULL );
856 cache->tempList = NULL;
857 g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
858 list = cache->tempList;
859 cache->tempList = NULL;
860 return list;
864 * Get all groups visitor function.
866 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
867 AddrItemObject *obj = ( AddrItemObject * ) value;
869 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
870 AddressCache *cache = data;
871 cache->tempList = g_list_append( cache->tempList, obj );
876 * Return link list of all groups in address cache. Note that the list contains
877 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
878 * this will destroy the address cache data!
879 * Return: List of items, or NULL if none.
881 GList *addrcache_get_all_groups( AddressCache *cache ) {
882 GList *list = NULL;
884 cm_return_val_if_fail( cache != NULL, NULL );
886 cache->tempList = NULL;
887 g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
888 list = cache->tempList;
889 cache->tempList = NULL;
890 return list;
894 * Remove folder from cache. Children are re-parented to parent folder.
895 * param: folder Folder to remove.
896 * return: Folder, or NULL if not found. Note that object should still be freed.
898 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
899 AddrItemObject *obj = NULL;
901 cm_return_val_if_fail( cache != NULL, NULL );
903 if( folder ) {
904 gchar *uid = ADDRITEM_ID(folder);
905 if( uid == NULL || *uid == '\0' ) return NULL;
906 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
907 if( obj ) {
908 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
909 GList *node;
910 AddrItemObject *aio;
911 if( ! parent ) parent = cache->rootFolder;
913 /* Re-parent children in folder */
914 node = folder->listFolder;
915 while( node ) {
916 aio = ( AddrItemObject * ) node->data;
917 parent->listFolder = g_list_append( parent->listFolder, aio );
918 aio->parent = ADDRITEM_OBJECT(parent);
919 node = g_list_next( node );
921 node = folder->listPerson;
922 while( node ) {
923 aio = ( AddrItemObject * ) node->data;
924 parent->listPerson = g_list_append( parent->listPerson, aio );
925 aio->parent = ADDRITEM_OBJECT(parent);
926 node = g_list_next( node );
928 node = folder->listGroup;
929 while( node ) {
930 aio = ( AddrItemObject * ) node->data;
931 parent->listGroup = g_list_append( parent->listGroup, aio );
932 aio->parent = ADDRITEM_OBJECT(parent);
933 node = g_list_next( node );
936 /* Remove folder from parent's list and hash table */
937 parent->listFolder = g_list_remove( parent->listFolder, folder );
938 ADDRITEM_PARENT(folder) = NULL;
939 g_hash_table_remove( cache->itemHash, uid );
940 cache->dirtyFlag = TRUE;
941 return folder;
944 return NULL;
948 * Remove folder from cache. Children are deleted.
949 * param: folder Folder to remove.
950 * return: Folder, or NULL if not found. Note that object should still be freed.
952 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
953 AddrItemObject *obj = NULL;
955 cm_return_val_if_fail( cache != NULL, NULL );
957 if( folder ) {
958 gchar *uid = ADDRITEM_ID(folder);
959 if( uid == NULL || *uid == '\0' ) return NULL;
960 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
961 if( obj ) {
962 ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
963 if( ! parent ) parent = cache->rootFolder;
965 /* Remove groups */
966 while( folder->listGroup ) {
967 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
968 item = addrcache_remove_group( cache, item );
969 if( item ) {
970 addritem_free_item_group( item );
971 item = NULL;
975 while( folder->listPerson ) {
976 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
977 item = addrcache_remove_person( cache, item );
978 if( item ) {
979 addritem_free_item_person( item );
980 item = NULL;
984 /* Recursive deletion of folder */
985 while( folder->listFolder ) {
986 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
987 item = addrcache_remove_folder_delete( cache, item );
988 if( item ) {
989 addritem_free_item_folder( item );
990 item = NULL;
994 /* Remove folder from parent's list and hash table */
995 parent->listFolder = g_list_remove( parent->listFolder, folder );
996 ADDRITEM_PARENT(folder) = NULL;
997 g_hash_table_remove( cache->itemHash, uid );
998 cache->dirtyFlag = TRUE;
999 return folder;
1002 return NULL;
1006 * Add person and address data to cache.
1007 * \param cache Cache.
1008 * \param folder Folder where to add person, or NULL for root folder.
1009 * \param name Common name.
1010 * \param address EMail address.
1011 * \param remarks Remarks.
1012 * \return Person added. Do not *NOT* to use the
1013 * <code>addrbook_free_xxx()</code> functions...; this will destroy
1014 * the address book data.
1016 ItemPerson *addrcache_add_contact(
1017 AddressCache *cache, ItemFolder *folder, const gchar *name,
1018 const gchar *address, const gchar *remarks )
1020 ItemPerson *person = NULL;
1021 ItemEMail *email = NULL;
1022 ItemFolder *f = folder;
1024 cm_return_val_if_fail( cache != NULL, NULL );
1026 if( ! f ) f = cache->rootFolder;
1028 /* Create person object */
1029 person = addritem_create_item_person();
1030 addritem_person_set_common_name( person, name );
1031 addrcache_id_person( cache, person );
1032 addrcache_folder_add_person( cache, f, person );
1034 /* Create email object */
1035 email = addritem_create_item_email();
1036 addritem_email_set_address( email, address );
1037 addritem_email_set_remarks( email, remarks );
1038 addrcache_id_email( cache, email );
1039 addritem_person_add_email( person, email );
1040 cache->dirtyFlag = TRUE;
1042 return person;
1046 * Create a new folder and add to address cache.
1047 * \param cache Address cache.
1048 * \param folder Parent folder where to add folder, or <i>NULL</i> for
1049 * root folder.
1050 * \return Folder that was created. This should <b>*NOT*</b> be
1051 * <code>g_free()</code> when done.
1053 ItemFolder *addrcache_add_new_folder( AddressCache *cache, ItemFolder *parent )
1055 ItemFolder *folder;
1056 ItemFolder *p = parent;
1058 cm_return_val_if_fail( cache != NULL, NULL );
1060 if( !p ) p = cache->rootFolder;
1061 folder = addritem_create_item_folder();
1062 addrcache_id_folder( cache, folder );
1063 if( addrcache_hash_add_folder( cache, folder ) ) {
1064 p->listFolder = g_list_append( p->listFolder, folder );
1065 ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
1066 addrcache_set_dirty( cache, TRUE );
1068 else {
1069 addritem_free_item_folder( folder );
1070 folder = NULL;
1072 return folder;
1076 * End of Source.