2 * Sylpheed -- 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.
29 #include "addrcache.h"
32 #define ID_TIME_OFFSET 998000000
33 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
35 static int _nextCacheID__
= 0;
38 * Generate next cache ID.
40 static int addrcache_next_cache_id() {
43 if( _nextCacheID__
== 0 ) {
46 retVal
= _nextCacheID__
;
52 * Create new address cache.
54 AddressCache
*addrcache_create() {
58 cache
= g_new0( AddressCache
, 1 );
59 cache
->itemHash
= g_hash_table_new( g_str_hash
, g_str_equal
);
60 cache
->cacheID
= g_strdup_printf( "%d", addrcache_next_cache_id() );
62 cache
->dataRead
= FALSE
;
63 cache
->modified
= FALSE
;
64 cache
->dirtyFlag
= FALSE
;
65 cache
->accessFlag
= FALSE
;
67 cache
->modifyTime
= 0;
69 /* Generate the next ID using system time */
73 cache
->nextID
= t
- ID_TIME_OFFSET
;
76 cache
->tempList
= NULL
;
77 cache
->rootFolder
= addritem_create_item_folder();
78 cache
->rootFolder
->isRoot
= TRUE
;
79 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
86 ItemFolder
*addrcache_get_root_folder( AddressCache
*cache
) {
87 cm_return_val_if_fail( cache
!= NULL
, NULL
);
88 return cache
->rootFolder
;
90 GList
*addrcache_get_list_folder( AddressCache
*cache
) {
91 cm_return_val_if_fail( cache
!= NULL
, NULL
);
92 return cache
->rootFolder
->listFolder
;
94 GList
*addrcache_get_list_person( AddressCache
*cache
) {
95 cm_return_val_if_fail( cache
!= NULL
, NULL
);
96 return cache
->rootFolder
->listPerson
;
98 gboolean
addrcache_get_dirty( AddressCache
*cache
) {
99 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
100 return cache
->dirtyFlag
;
102 void addrcache_set_dirty( AddressCache
*cache
, const gboolean value
) {
103 cm_return_if_fail( cache
!= NULL
);
104 cache
->dirtyFlag
= value
;
106 gchar
*addrcache_get_name( AddressCache
*cache
) {
107 cm_return_val_if_fail( cache
!= NULL
, NULL
);
110 void addrcache_set_name( AddressCache
*cache
, const gchar
*value
) {
111 cm_return_if_fail( cache
!= NULL
);
112 cache
->name
= mgu_replace_string( cache
->name
, value
);
113 g_strstrip( cache
->name
);
114 cache
->dirtyFlag
= TRUE
;
120 static void addrcache_next_id( AddressCache
*cache
) {
121 cm_return_if_fail( cache
!= NULL
);
126 * Refresh internal variables. This can be used force a reload.
128 void addrcache_refresh( AddressCache
*cache
) {
129 cache
->dataRead
= FALSE
;
130 cache
->modified
= TRUE
;
131 cache
->accessFlag
= FALSE
;
132 cache
->modifyTime
= 0;
136 * Free hash table visitor function.
138 static gint
addrcache_free_item_vis( gpointer key
, gpointer value
, gpointer data
) {
139 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
141 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_PERSON
) {
142 addritem_free_item_person( ( ItemPerson
* ) obj
);
144 else if( ADDRITEM_TYPE(obj
) == ITEMTYPE_EMAIL
) {
145 addritem_free_item_email( ( ItemEMail
* ) obj
);
147 else if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
148 addritem_free_item_group( ( ItemGroup
* ) obj
);
150 else if( ADDRITEM_TYPE(obj
) == ITEMTYPE_FOLDER
) {
151 addritem_free_item_folder( ( ItemFolder
* ) obj
);
159 * Free hash table of address cache items.
161 static void addrcache_free_item_hash( GHashTable
*table
) {
162 cm_return_if_fail( table
!= NULL
);
163 g_hash_table_foreach_remove( table
, addrcache_free_item_vis
, NULL
);
167 * Free up folders and groups.
169 static void addrcache_free_all_folders( ItemFolder
*parent
) {
172 if( parent
== NULL
) return;
174 node
= parent
->listFolder
;
176 ItemFolder
*folder
= node
->data
;
177 addrcache_free_all_folders( folder
);
179 node
= g_list_next( node
);
181 g_list_free( parent
->listPerson
);
182 g_list_free( parent
->listGroup
);
183 g_list_free( parent
->listFolder
);
184 parent
->listPerson
= NULL
;
185 parent
->listGroup
= NULL
;
186 parent
->listFolder
= NULL
;
190 * Clear the address cache.
192 void addrcache_clear( AddressCache
*cache
) {
193 cm_return_if_fail( cache
!= NULL
);
195 /* g_print( "...addrcache_clear :%s:\n", cache->name ); */
196 /* Free up folders and hash table */
197 addrcache_free_all_folders( cache
->rootFolder
);
198 addrcache_free_item_hash( cache
->itemHash
);
199 g_hash_table_destroy( cache
->itemHash
);
200 cache
->itemHash
= NULL
;
201 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
202 addritem_free_item_folder( cache
->rootFolder
);
203 cache
->rootFolder
= NULL
;
204 if( cache
->tempList
) g_list_free( cache
->tempList
);
205 cache
->tempList
= NULL
;
207 /* Reset to initial state */
208 cache
->itemHash
= g_hash_table_new( g_str_hash
, g_str_equal
);
209 cache
->rootFolder
= addritem_create_item_folder();
210 cache
->rootFolder
->isRoot
= TRUE
;
211 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
213 addrcache_refresh( cache
);
217 * Free address cache.
219 void addrcache_free( AddressCache
*cache
) {
220 cm_return_if_fail( cache
!= NULL
);
222 cache
->dirtyFlag
= FALSE
;
223 addrcache_free_all_folders( cache
->rootFolder
);
224 addrcache_free_item_hash( cache
->itemHash
);
225 g_hash_table_destroy( cache
->itemHash
);
226 cache
->itemHash
= NULL
;
227 ADDRITEM_PARENT(cache
->rootFolder
) = NULL
;
228 addritem_free_item_folder( cache
->rootFolder
);
229 cache
->rootFolder
= NULL
;
230 g_list_free( cache
->tempList
);
231 cache
->tempList
= NULL
;
232 g_free( cache
->cacheID
);
233 cache
->cacheID
= NULL
;
234 g_free( cache
->name
);
240 * Check whether file has changed by comparing with cache.
241 * return: TRUE if file has changed.
243 gboolean
addrcache_check_file( AddressCache
*cache
, gchar
*path
) {
248 if( 0 == g_stat( path
, &filestat
) ) {
249 if( filestat
.st_mtime
== cache
->modifyTime
) retVal
= FALSE
;
256 * Save file time to cache.
257 * return: TRUE if time marked.
259 gboolean
addrcache_mark_file( AddressCache
*cache
, gchar
*path
) {
260 gboolean retVal
= FALSE
;
263 if( 0 == g_stat( path
, &filestat
) ) {
264 cache
->modifyTime
= filestat
.st_mtime
;
272 * Dump entire address cache hash table contents.
274 void addrcache_print( AddressCache
*cache
, FILE *stream
) {
275 cm_return_if_fail( cache
!= NULL
);
276 fprintf( stream
, "AddressCache:\n" );
277 fprintf( stream
, "cache id : %s\n", cache
->cacheID
);
278 fprintf( stream
, "next id : %d\n", cache
->nextID
);
279 fprintf( stream
, "name : %s\n", cache
->name
);
280 fprintf( stream
, "mod time : %ld\n", (long int)cache
->modifyTime
);
281 fprintf( stream
, "modified : %s\n", cache
->modified
? "yes" : "no" );
282 fprintf( stream
, "data read: %s\n", cache
->dataRead
? "yes" : "no" );
286 * Allocate ID for person.
288 void addrcache_id_person( AddressCache
*cache
, ItemPerson
*person
) {
289 cm_return_if_fail( cache
!= NULL
);
290 cm_return_if_fail( person
!= NULL
);
291 if( ADDRITEM_ID(person
) ) return;
292 addrcache_next_id( cache
);
293 ADDRITEM_ID(person
) = g_strdup_printf( "%d", cache
->nextID
);
297 * Allocate ID for group.
299 void addrcache_id_group( AddressCache
*cache
, ItemGroup
*group
) {
300 cm_return_if_fail( cache
!= NULL
);
301 cm_return_if_fail( group
!= NULL
);
302 if( ADDRITEM_ID(group
) ) return;
303 addrcache_next_id( cache
);
304 ADDRITEM_ID(group
) = g_strdup_printf( "%d", cache
->nextID
);
308 * Allocate ID for folder.
310 void addrcache_id_folder( AddressCache
*cache
, ItemFolder
*folder
) {
311 cm_return_if_fail( cache
!= NULL
);
312 cm_return_if_fail( folder
!= NULL
);
313 if( ADDRITEM_ID(folder
) ) return;
314 addrcache_next_id( cache
);
315 ADDRITEM_ID(folder
) = g_strdup_printf( "%d", cache
->nextID
);
319 * Allocate ID for email address.
321 void addrcache_id_email( AddressCache
*cache
, ItemEMail
*email
) {
322 cm_return_if_fail( cache
!= NULL
);
323 cm_return_if_fail( email
!= NULL
);
324 if( ADDRITEM_ID(email
) ) return;
325 addrcache_next_id( cache
);
326 ADDRITEM_ID(email
) = g_strdup_printf( "%d", cache
->nextID
);
330 * Allocate ID for user attribute.
332 void addrcache_id_attribute( AddressCache
*cache
, UserAttribute
*attrib
) {
333 cm_return_if_fail( cache
!= NULL
);
334 cm_return_if_fail( attrib
!= NULL
);
335 if( attrib
->uid
) return;
336 addrcache_next_id( cache
);
337 attrib
->uid
= g_strdup_printf( "%d", cache
->nextID
);
341 * Add person to hash table.
342 * return: TRUE if item added.
344 gboolean
addrcache_hash_add_person( AddressCache
*cache
, ItemPerson
*person
) {
345 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(person
) ) ) {
348 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(person
), person
);
353 * Add email to hash table.
354 * return: TRUE if item added.
356 static gboolean
addrcache_hash_add_email( AddressCache
*cache
, ItemEMail
*email
) {
357 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(email
) ) ) {
360 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(email
), email
);
365 * Add group to hash table.
366 * return: TRUE if item added.
368 gboolean
addrcache_hash_add_group( AddressCache
*cache
, ItemGroup
*group
) {
369 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
370 cm_return_val_if_fail( group
!= NULL
, FALSE
);
372 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(group
) ) ) {
375 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(group
), group
);
380 * Add folder to hash table.
381 * return: TRUE if item added.
383 gboolean
addrcache_hash_add_folder( AddressCache
*cache
, ItemFolder
*folder
) {
384 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
385 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
387 if( g_hash_table_lookup( cache
->itemHash
, ADDRITEM_ID(folder
) ) ) {
390 g_hash_table_insert( cache
->itemHash
, ADDRITEM_ID(folder
), folder
);
395 * Add person to specified folder in cache.
397 gboolean
addrcache_folder_add_person( AddressCache
*cache
, ItemFolder
*folder
, ItemPerson
*item
) {
398 gboolean retVal
= FALSE
;
400 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
401 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
402 cm_return_val_if_fail( item
!= NULL
, FALSE
);
404 retVal
= addrcache_hash_add_person( cache
, item
);
406 addritem_folder_add_person( folder
, item
);
407 cache
->dirtyFlag
= TRUE
;
413 * Add folder to specified folder in cache.
415 gboolean
addrcache_folder_add_folder( AddressCache
*cache
, ItemFolder
*folder
, ItemFolder
*item
) {
416 gboolean retVal
= FALSE
;
418 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
419 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
420 cm_return_val_if_fail( item
!= NULL
, FALSE
);
422 retVal
= addrcache_hash_add_folder( cache
, item
);
424 addritem_folder_add_folder( folder
, item
);
425 cache
->dirtyFlag
= TRUE
;
431 * Add folder to specified folder in cache.
433 gboolean
addrcache_folder_add_group( AddressCache
*cache
, ItemFolder
*folder
, ItemGroup
*item
) {
434 gboolean retVal
= FALSE
;
436 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
437 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
438 cm_return_val_if_fail( item
!= NULL
, FALSE
);
440 retVal
= addrcache_hash_add_group( cache
, item
);
442 addritem_folder_add_group( folder
, item
);
443 cache
->dirtyFlag
= TRUE
;
449 * Add person to address cache.
450 * return: TRUE if item added.
452 gboolean
addrcache_add_person( AddressCache
*cache
, ItemPerson
*person
) {
453 gboolean retVal
= FALSE
;
455 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
456 cm_return_val_if_fail( person
!= NULL
, FALSE
);
458 retVal
= addrcache_hash_add_person( cache
, person
);
460 addritem_folder_add_person( cache
->rootFolder
, person
);
461 cache
->dirtyFlag
= TRUE
;
467 * Add EMail address to person.
468 * return: TRUE if item added.
470 gboolean
addrcache_person_add_email( AddressCache
*cache
, ItemPerson
*person
, ItemEMail
*email
) {
471 gboolean retVal
= FALSE
;
473 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
474 cm_return_val_if_fail( person
!= NULL
, FALSE
);
475 cm_return_val_if_fail( email
!= NULL
, FALSE
);
477 retVal
= addrcache_hash_add_email( cache
, email
);
479 addritem_person_add_email( person
, email
);
480 cache
->dirtyFlag
= TRUE
;
486 * Add group to address cache.
487 * return: TRUE if item added.
489 gboolean
addrcache_add_group( AddressCache
*cache
, ItemGroup
*group
) {
490 gboolean retVal
= FALSE
;
492 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
493 cm_return_val_if_fail( group
!= NULL
, FALSE
);
495 retVal
= addrcache_hash_add_group( cache
, group
);
497 addritem_folder_add_group( cache
->rootFolder
, group
);
498 cache
->dirtyFlag
= TRUE
;
504 * Add EMail address to person.
505 * return: TRUE if item added.
507 gboolean
addrcache_group_add_email( AddressCache
*cache
, ItemGroup
*group
, ItemEMail
*email
) {
508 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
509 cm_return_val_if_fail( group
!= NULL
, FALSE
);
510 cm_return_val_if_fail( email
!= NULL
, FALSE
);
512 addritem_group_add_email( group
, email
);
513 cache
->dirtyFlag
= TRUE
;
518 * Add folder to address cache.
519 * return: TRUE if item added.
521 gboolean
addrcache_add_folder( AddressCache
*cache
, ItemFolder
*folder
) {
522 gboolean retVal
= FALSE
;
524 cm_return_val_if_fail( cache
!= NULL
, FALSE
);
525 cm_return_val_if_fail( folder
!= NULL
, FALSE
);
527 retVal
= addrcache_hash_add_folder( cache
, folder
);
529 addritem_folder_add_folder( cache
->rootFolder
, folder
);
530 cache
->dirtyFlag
= TRUE
;
536 * Move person to destination folder.
537 * Enter: cache Cache.
538 * person Person to move.
539 * target Target folder.
541 void addrcache_folder_move_person(
542 AddressCache
*cache
, ItemPerson
*person
, ItemFolder
*target
)
546 cm_return_if_fail( cache
!= NULL
);
547 cm_return_if_fail( person
!= NULL
);
549 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(person
);
550 if( ! parent
) parent
= cache
->rootFolder
;
551 parent
->listPerson
= g_list_remove( parent
->listPerson
, person
);
552 target
->listPerson
= g_list_append( target
->listPerson
, person
);
553 ADDRITEM_PARENT(person
) = ADDRITEM_OBJECT(target
);
554 cache
->dirtyFlag
= TRUE
;
558 * Move group to destination folder.
559 * Enter: cache Cache.
560 * group Group to move.
561 * target Target folder.
563 void addrcache_folder_move_group(
564 AddressCache
*cache
, ItemGroup
*group
, ItemFolder
*target
)
568 cm_return_if_fail( cache
!= NULL
);
569 cm_return_if_fail( group
!= NULL
);
571 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(group
);
572 if( ! parent
) parent
= cache
->rootFolder
;
573 parent
->listGroup
= g_list_remove( parent
->listGroup
, group
);
574 target
->listGroup
= g_list_append( target
->listGroup
, group
);
575 ADDRITEM_PARENT(group
) = ADDRITEM_OBJECT(target
);
576 cache
->dirtyFlag
= TRUE
;
580 * Move folder to destination folder.
581 * Enter: cache Cache.
582 * folder Folder to move.
583 * target Target folder.
585 void addrcache_folder_move_folder(
586 AddressCache
*cache
, ItemFolder
*folder
, ItemFolder
*target
)
590 cm_return_if_fail( cache
!= NULL
);
591 cm_return_if_fail( folder
!= NULL
);
593 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(folder
);
594 if( ! parent
) parent
= cache
->rootFolder
;
595 parent
->listFolder
= g_list_remove( parent
->listFolder
, folder
);
596 target
->listFolder
= g_list_append( target
->listFolder
, folder
);
597 ADDRITEM_PARENT(folder
) = ADDRITEM_OBJECT(target
);
598 cache
->dirtyFlag
= TRUE
;
602 * Return pointer to object (either person or group) for specified ID.
603 * param: uid Object ID.
604 * return: Object, or NULL if not found.
606 AddrItemObject
*addrcache_get_object( AddressCache
*cache
, const gchar
*uid
) {
607 AddrItemObject
*obj
= NULL
;
610 cm_return_val_if_fail( cache
!= NULL
, NULL
);
612 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
613 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
615 /* Check for matching UID */
616 uidH
= ADDRITEM_ID(obj
);
618 if( strcmp( uidH
, uid
) == 0 ) return obj
;
625 * Find email address in address cache.
626 * param: eid EMail ID.
627 * return: email object for specified object ID and email ID, or NULL if not found.
629 ItemEMail
*addrcache_get_email( AddressCache
*cache
, const gchar
*eid
) {
630 ItemEMail
*email
= NULL
;
631 AddrItemObject
*obj
= addrcache_get_object( cache
, eid
);
634 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_EMAIL
) {
635 email
= ( ItemEMail
* ) obj
;
642 * Remove group from address cache.
643 * param: group Group to remove.
644 * return: Group, or NULL if not found. Note that object should still be freed.
646 ItemGroup
*addrcache_remove_group( AddressCache
*cache
, ItemGroup
*group
) {
647 AddrItemObject
*obj
= NULL
;
649 cm_return_val_if_fail( cache
!= NULL
, NULL
);
652 gchar
*uid
= ADDRITEM_ID(group
);
653 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
654 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
656 ItemFolder
*parent
= ( ItemFolder
* ) ADDRITEM_PARENT(group
);
657 if( ! parent
) parent
= cache
->rootFolder
;
659 /* Remove group from parent's list and hash table */
660 parent
->listGroup
= g_list_remove( parent
->listGroup
, obj
);
661 g_hash_table_remove( cache
->itemHash
, uid
);
662 cache
->dirtyFlag
= TRUE
;
670 * Remove specified email from address cache. Note that object is only
671 * removed from cache and not parent objects.
672 * param: email EMail to remove.
673 * return: EMail, or NULL if not found. Note that object should still be freed.
675 ItemEMail
*addrcache_remove_email( AddressCache
*cache
, ItemEMail
*email
) {
676 AddrItemObject
*obj
= NULL
;
678 cm_return_val_if_fail( cache
!= NULL
, NULL
);
681 gchar
*eid
= ADDRITEM_ID(email
);
682 if( eid
== NULL
|| *eid
== '\0' ) return NULL
;
683 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, eid
);
685 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_EMAIL
) {
686 /* Remove email addresses from hash table. */
687 g_hash_table_remove( cache
->itemHash
, eid
);
688 cache
->dirtyFlag
= TRUE
;
697 * Hash table visitor function to remove email from group.
699 static void addrcache_allgrp_rem_email_vis( gpointer key
, gpointer value
, gpointer data
) {
700 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
701 ItemEMail
*email
= ( ItemEMail
* ) data
;
703 if( ! email
) return;
704 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
705 ItemGroup
*group
= ( ItemGroup
* ) value
;
707 /* Remove each email address that belongs to the person from the list */
708 group
->listEMail
= g_list_remove( group
->listEMail
, email
);
714 * Remove specified person from address cache.
715 * param: person Person to remove.
716 * return: Person, or NULL if not found. Note that object should still be freed.
718 ItemPerson
*addrcache_remove_person( AddressCache
*cache
, ItemPerson
*person
) {
719 AddrItemObject
*obj
= NULL
;
722 cm_return_val_if_fail( cache
!= NULL
, NULL
);
725 uid
= ADDRITEM_ID(person
);
726 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
727 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
729 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_PERSON
) {
733 /* Remove all email addresses for person */
734 /* from groups and from hash table */
735 node
= person
->listEMail
;
741 g_hash_table_foreach( cache
->itemHash
,
742 addrcache_allgrp_rem_email_vis
, email
);
743 eid
= ADDRITEM_ID( email
);
744 g_hash_table_remove( cache
->itemHash
, eid
);
745 node
= g_list_next( node
);
748 /* Remove person from owning folder */
749 parent
= ( ItemFolder
* ) ADDRITEM_PARENT(person
);
750 if( ! parent
) parent
= cache
->rootFolder
;
751 parent
->listPerson
= g_list_remove( parent
->listPerson
, person
);
752 g_hash_table_remove( cache
->itemHash
, uid
);
753 cache
->dirtyFlag
= TRUE
;
762 * Remove email address in address cache for specified person.
763 * param: person Person.
764 * email EMail to remove.
765 * return: EMail object, or NULL if not found. Note that object should still be freed.
767 ItemEMail
*addrcache_person_remove_email( AddressCache
*cache
, ItemPerson
*person
, ItemEMail
*email
) {
768 ItemEMail
*found
= NULL
;
770 cm_return_val_if_fail( cache
!= NULL
, NULL
);
772 if( person
&& email
) {
773 found
= addritem_person_remove_email( person
, email
);
775 /* Remove email from all groups. */
776 g_hash_table_foreach( cache
->itemHash
, addrcache_allgrp_rem_email_vis
, email
);
778 /* Remove email from person's address list */
779 if( person
->listEMail
) {
780 person
->listEMail
= g_list_remove( person
->listEMail
, email
);
782 /* Unlink reference to person. */
783 ADDRITEM_PARENT(email
) = NULL
;
784 cache
->dirtyFlag
= TRUE
;
791 * Group visitor function.
793 static void addrcache_get_grp_person_vis( gpointer key
, gpointer value
, gpointer data
) {
794 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
796 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
797 AddressCache
*cache
= data
;
798 ItemGroup
*group
= ( ItemGroup
* ) obj
;
799 ItemPerson
*person
= ( ItemPerson
* ) cache
->tempList
->data
;
800 GList
*node
= group
->listEMail
;
802 ItemEMail
*email
= ( ItemEMail
* ) node
->data
;
803 if( ADDRITEM_PARENT(email
) == ADDRITEM_OBJECT(person
) ) {
804 if( ! g_list_find( cache
->tempList
, group
) ) {
805 cache
->tempList
= g_list_append( cache
->tempList
, group
);
808 node
= g_list_next( node
);
814 * Return linked list of groups which contain a reference to specified person's email
817 GList
*addrcache_get_group_for_person( AddressCache
*cache
, ItemPerson
*person
) {
820 cm_return_val_if_fail( cache
!= NULL
, NULL
);
822 cache
->tempList
= NULL
;
823 cache
->tempList
= g_list_append( cache
->tempList
, person
);
824 g_hash_table_foreach( cache
->itemHash
, addrcache_get_grp_person_vis
, cache
);
825 cache
->tempList
= g_list_remove( cache
->tempList
, person
);
826 list
= cache
->tempList
;
827 cache
->tempList
= NULL
;
832 * Get all person visitor function.
834 static void addrcache_get_all_persons_vis( gpointer key
, gpointer value
, gpointer data
) {
835 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
837 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_PERSON
) {
838 AddressCache
*cache
= data
;
839 cache
->tempList
= g_list_append( cache
->tempList
, obj
);
844 * Return link list of all persons in address cache. Note that the list contains
845 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
846 * this will destroy the address cache data!
847 * Return: List of items, or NULL if none.
849 GList
*addrcache_get_all_persons( AddressCache
*cache
) {
852 cm_return_val_if_fail( cache
!= NULL
, NULL
);
854 cache
->tempList
= NULL
;
855 g_hash_table_foreach( cache
->itemHash
, addrcache_get_all_persons_vis
, cache
);
856 list
= cache
->tempList
;
857 cache
->tempList
= NULL
;
862 * Get all groups visitor function.
864 static void addrcache_get_all_groups_vis( gpointer key
, gpointer value
, gpointer data
) {
865 AddrItemObject
*obj
= ( AddrItemObject
* ) value
;
867 if( ADDRITEM_TYPE(obj
) == ITEMTYPE_GROUP
) {
868 AddressCache
*cache
= data
;
869 cache
->tempList
= g_list_append( cache
->tempList
, obj
);
874 * Return link list of all groups in address cache. Note that the list contains
875 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
876 * this will destroy the address cache data!
877 * Return: List of items, or NULL if none.
879 GList
*addrcache_get_all_groups( AddressCache
*cache
) {
882 cm_return_val_if_fail( cache
!= NULL
, NULL
);
884 cache
->tempList
= NULL
;
885 g_hash_table_foreach( cache
->itemHash
, addrcache_get_all_groups_vis
, cache
);
886 list
= cache
->tempList
;
887 cache
->tempList
= NULL
;
892 * Remove folder from cache. Children are re-parented to parent folder.
893 * param: folder Folder to remove.
894 * return: Folder, or NULL if not found. Note that object should still be freed.
896 ItemFolder
*addrcache_remove_folder( AddressCache
*cache
, ItemFolder
*folder
) {
897 AddrItemObject
*obj
= NULL
;
899 cm_return_val_if_fail( cache
!= NULL
, NULL
);
902 gchar
*uid
= ADDRITEM_ID(folder
);
903 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
904 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
906 ItemFolder
*parent
= ( ItemFolder
* ) ADDRITEM_PARENT(folder
);
909 if( ! parent
) parent
= cache
->rootFolder
;
911 /* Re-parent children in folder */
912 node
= folder
->listFolder
;
914 aio
= ( AddrItemObject
* ) node
->data
;
915 parent
->listFolder
= g_list_append( parent
->listFolder
, aio
);
916 aio
->parent
= ADDRITEM_OBJECT(parent
);
917 node
= g_list_next( node
);
919 node
= folder
->listPerson
;
921 aio
= ( AddrItemObject
* ) node
->data
;
922 parent
->listPerson
= g_list_append( parent
->listPerson
, aio
);
923 aio
->parent
= ADDRITEM_OBJECT(parent
);
924 node
= g_list_next( node
);
926 node
= folder
->listGroup
;
928 aio
= ( AddrItemObject
* ) node
->data
;
929 parent
->listGroup
= g_list_append( parent
->listGroup
, aio
);
930 aio
->parent
= ADDRITEM_OBJECT(parent
);
931 node
= g_list_next( node
);
934 /* Remove folder from parent's list and hash table */
935 parent
->listFolder
= g_list_remove( parent
->listFolder
, folder
);
936 ADDRITEM_PARENT(folder
) = NULL
;
937 g_hash_table_remove( cache
->itemHash
, uid
);
938 cache
->dirtyFlag
= TRUE
;
946 * Remove folder from cache. Children are deleted.
947 * param: folder Folder to remove.
948 * return: Folder, or NULL if not found. Note that object should still be freed.
950 ItemFolder
*addrcache_remove_folder_delete( AddressCache
*cache
, ItemFolder
*folder
) {
951 AddrItemObject
*obj
= NULL
;
953 cm_return_val_if_fail( cache
!= NULL
, NULL
);
956 gchar
*uid
= ADDRITEM_ID(folder
);
957 if( uid
== NULL
|| *uid
== '\0' ) return NULL
;
958 obj
= ( AddrItemObject
* ) g_hash_table_lookup( cache
->itemHash
, uid
);
960 ItemFolder
*parent
= ( ItemFolder
* ) ADDRITEM_PARENT(folder
);
961 if( ! parent
) parent
= cache
->rootFolder
;
964 while( folder
->listGroup
) {
965 ItemGroup
*item
= ( ItemGroup
* ) folder
->listGroup
->data
;
966 item
= addrcache_remove_group( cache
, item
);
968 addritem_free_item_group( item
);
973 while( folder
->listPerson
) {
974 ItemPerson
*item
= ( ItemPerson
* ) folder
->listPerson
->data
;
975 item
= addrcache_remove_person( cache
, item
);
977 addritem_free_item_person( item
);
982 /* Recursive deletion of folder */
983 while( folder
->listFolder
) {
984 ItemFolder
*item
= ( ItemFolder
* ) folder
->listFolder
->data
;
985 item
= addrcache_remove_folder_delete( cache
, item
);
987 addritem_free_item_folder( item
);
992 /* Remove folder from parent's list and hash table */
993 parent
->listFolder
= g_list_remove( parent
->listFolder
, folder
);
994 ADDRITEM_PARENT(folder
) = NULL
;
995 g_hash_table_remove( cache
->itemHash
, uid
);
996 cache
->dirtyFlag
= TRUE
;
1004 * Add person and address data to cache.
1005 * \param cache Cache.
1006 * \param folder Folder where to add person, or NULL for root folder.
1007 * \param name Common name.
1008 * \param address EMail address.
1009 * \param remarks Remarks.
1010 * \return Person added. Do not *NOT* to use the
1011 * <code>addrbook_free_xxx()</code> functions...; this will destroy
1012 * the address book data.
1014 ItemPerson
*addrcache_add_contact(
1015 AddressCache
*cache
, ItemFolder
*folder
, const gchar
*name
,
1016 const gchar
*address
, const gchar
*remarks
)
1018 ItemPerson
*person
= NULL
;
1019 ItemEMail
*email
= NULL
;
1020 ItemFolder
*f
= folder
;
1022 cm_return_val_if_fail( cache
!= NULL
, NULL
);
1024 if( ! f
) f
= cache
->rootFolder
;
1026 /* Create person object */
1027 person
= addritem_create_item_person();
1028 addritem_person_set_common_name( person
, name
);
1029 addrcache_id_person( cache
, person
);
1030 addrcache_folder_add_person( cache
, f
, person
);
1032 /* Create email object */
1033 email
= addritem_create_item_email();
1034 addritem_email_set_address( email
, address
);
1035 addritem_email_set_remarks( email
, remarks
);
1036 addrcache_id_email( cache
, email
);
1037 addritem_person_add_email( person
, email
);
1038 cache
->dirtyFlag
= TRUE
;
1044 * Create a new folder and add to address cache.
1045 * \param cache Address cache.
1046 * \param folder Parent folder where to add folder, or <i>NULL</i> for
1048 * \return Folder that was created. This should <b>*NOT*</b> be
1049 * <code>g_free()</code> when done.
1051 ItemFolder
*addrcache_add_new_folder( AddressCache
*cache
, ItemFolder
*parent
)
1054 ItemFolder
*p
= parent
;
1056 cm_return_val_if_fail( cache
!= NULL
, NULL
);
1058 if( !p
) p
= cache
->rootFolder
;
1059 folder
= addritem_create_item_folder();
1060 addrcache_id_folder( cache
, folder
);
1061 if( addrcache_hash_add_folder( cache
, folder
) ) {
1062 p
->listFolder
= g_list_append( p
->listFolder
, folder
);
1063 ADDRITEM_PARENT(folder
) = ADDRITEM_OBJECT(p
);
1064 addrcache_set_dirty( cache
, TRUE
);
1067 addritem_free_item_folder( folder
);