cleaned up conflicting declarations of imageview_show_image()
[claws.git] / src / addrcache.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2001-2002 Match Grun
4  *
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.
9  *
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.
14  *
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.
18  */
19
20 /*
21  * Functions to maintain address cache.
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/stat.h>
27
28 #include "mgutils.h"
29 #include "addritem.h"
30 #include "addrcache.h"
31
32 #define ID_TIME_OFFSET             998000000
33 #define ADDRCACHE_MAX_SEARCH_COUNT 1000
34
35 static int _nextCacheID__ = 0;
36
37 /*
38  * Generate next cache ID.
39  */
40 static int addrcache_next_cache_id() {
41         int retVal;
42
43         if( _nextCacheID__ == 0 ) {
44                 _nextCacheID__ = 1;
45         }
46         retVal = _nextCacheID__;
47         ++_nextCacheID__;
48         return retVal;
49 }
50
51 /*
52 * Create new address cache.
53 */
54 AddressCache *addrcache_create() {
55         AddressCache *cache;
56         gint t;
57
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() );
61
62         cache->dataRead = FALSE;
63         cache->modified = FALSE;
64         cache->dirtyFlag = FALSE;
65         cache->accessFlag = FALSE;
66         cache->name = NULL;
67         cache->modifyTime = 0;
68
69         /* Generate the next ID using system time */
70         cache->nextID = 1;
71         t = time( NULL );
72         if( t > 0 ) {
73                 cache->nextID = t - ID_TIME_OFFSET;
74         }
75
76         cache->tempList = NULL;
77         cache->rootFolder = addritem_create_item_folder();
78         cache->rootFolder->isRoot = TRUE;
79         ADDRITEM_PARENT(cache->rootFolder) = NULL;
80         return cache;
81 }
82
83 /*
84 * Properties.
85 */
86 ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
87         g_return_val_if_fail( cache != NULL, NULL );
88         return cache->rootFolder;
89 }
90 GList *addrcache_get_list_folder( AddressCache *cache ) {
91         g_return_val_if_fail( cache != NULL, NULL );
92         return cache->rootFolder->listFolder;
93 }
94 GList *addrcache_get_list_person( AddressCache *cache ) {
95         g_return_val_if_fail( cache != NULL, NULL );
96         return cache->rootFolder->listPerson;
97 }
98 gboolean addrcache_get_dirty( AddressCache *cache ) {
99         g_return_val_if_fail( cache != NULL, FALSE );
100         return cache->dirtyFlag;
101 }
102 void addrcache_set_dirty( AddressCache *cache, const gboolean value ) {
103         g_return_if_fail( cache != NULL );
104         cache->dirtyFlag = value;
105 }
106 gboolean addrcache_get_modified( AddressCache *cache ) {
107         g_return_val_if_fail( cache != NULL, FALSE );
108         return cache->modified;
109 }
110 void addrcache_set_modified( AddressCache *cache, const gboolean value ) {
111         g_return_if_fail( cache != NULL );
112         cache->modified = value;
113 }
114 gboolean addrcache_get_read_flag( AddressCache *cache ) {
115         g_return_val_if_fail( cache != NULL, FALSE );
116         return cache->dataRead;
117 }
118 void addrcache_set_read_flag( AddressCache *cache, const gboolean value ) {
119         g_return_if_fail( cache != NULL );
120         cache->dataRead = value;
121 }
122 gboolean addrcache_get_accessed( AddressCache *cache ) {
123         g_return_val_if_fail( cache != NULL, FALSE );
124         return cache->accessFlag;
125 }
126 void addrcache_set_accessed( AddressCache *cache, const gboolean value ) {
127         g_return_if_fail( cache != NULL );
128         cache->accessFlag = value;
129 }
130 gchar *addrcache_get_name( AddressCache *cache ) {
131         g_return_val_if_fail( cache != NULL, NULL );
132         return cache->name;
133 }
134 void addrcache_set_name( AddressCache *cache, const gchar *value ) {
135         g_return_if_fail( cache != NULL );
136         cache->name = mgu_replace_string( cache->name, value );
137         g_strstrip( cache->name );
138         cache->dirtyFlag = TRUE;
139 }
140
141 /*
142 * Generate next ID.
143 */
144 void addrcache_next_id( AddressCache *cache ) {
145         g_return_if_fail( cache != NULL );
146         cache->nextID++;
147 }
148
149 /*
150 * Refresh internal variables. This can be used force a reload.
151 */
152 void addrcache_refresh( AddressCache *cache ) {
153         cache->dataRead = FALSE;
154         cache->modified = TRUE;
155         cache->accessFlag = FALSE;
156         cache->modifyTime = 0;
157 }
158
159 /*
160 * Free hash table visitor function.
161 */
162 static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
163         AddrItemObject *obj = ( AddrItemObject * ) value;
164
165         if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
166                 addritem_free_item_person( ( ItemPerson * ) obj );
167         }
168         else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
169                 addritem_free_item_email( ( ItemEMail * ) obj );
170         }
171         else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
172                 addritem_free_item_group( ( ItemGroup * ) obj );
173         }
174         else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
175                 addritem_free_item_folder( ( ItemFolder * ) obj );
176         }
177         key = NULL;
178         value = NULL;
179         return TRUE;
180 }
181
182 /*
183 * Free hash table of address cache items.
184 */
185 static void addrcache_free_item_hash( GHashTable *table ) {
186         g_return_if_fail( table != NULL );
187         g_hash_table_freeze( table );
188         g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
189         g_hash_table_thaw( table );
190 }
191
192 /*
193 * Free up folders and groups.
194 */
195 static void addrcache_free_all_folders( ItemFolder *parent ) {
196         GList *node;
197
198         if( parent == NULL ) return;
199
200         node = parent->listFolder;
201         while( node ) {
202                 ItemFolder *folder = node->data;
203                 addrcache_free_all_folders( folder );
204                 node->data = NULL;
205                 node = g_list_next( node );
206         }
207         g_list_free( parent->listPerson );
208         g_list_free( parent->listGroup );
209         g_list_free( parent->listFolder );
210         parent->listPerson = NULL;
211         parent->listGroup = NULL;
212         parent->listFolder = NULL;
213 }
214
215 /*
216 * Clear the address cache.
217 */
218 void addrcache_clear( AddressCache *cache ) {
219         g_return_if_fail( cache != NULL );
220
221         /* printf( "...addrcache_clear :%s:\n", cache->name ); */
222         /* Free up folders and hash table */
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         if( cache->tempList ) g_list_free( cache->tempList );
231         cache->tempList = NULL;
232
233         /* Reset to initial state */
234         cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
235         cache->rootFolder = addritem_create_item_folder();
236         cache->rootFolder->isRoot = TRUE;
237         ADDRITEM_PARENT(cache->rootFolder) = NULL;
238
239         addrcache_refresh( cache );
240 }
241
242 /*
243 * Free address cache.
244 */
245 void addrcache_free( AddressCache *cache ) {
246         g_return_if_fail( cache != NULL );
247
248         cache->dirtyFlag = FALSE;
249         addrcache_free_all_folders( cache->rootFolder );
250         addrcache_free_item_hash( cache->itemHash );
251         g_hash_table_destroy( cache->itemHash );
252         cache->itemHash = NULL;
253         ADDRITEM_PARENT(cache->rootFolder) = NULL;
254         addritem_free_item_folder( cache->rootFolder );
255         cache->rootFolder = NULL;
256         g_list_free( cache->tempList );
257         cache->tempList = NULL;
258         g_free( cache->cacheID );
259         cache->cacheID = NULL;
260         g_free( cache->name );
261         cache->name = NULL;
262         g_free( cache );
263 }
264
265 /*
266 * Check whether file has changed by comparing with cache.
267 * return: TRUE if file has changed.
268 */
269 gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
270         gboolean retVal;
271         struct stat filestat;
272         retVal = TRUE;
273         if( path ) {
274                 if( 0 == lstat( path, &filestat ) ) {
275                         if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
276                 }
277         }
278         return retVal;
279 }
280
281 /*
282 * Save file time to cache.
283 * return: TRUE if time marked.
284 */
285 gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
286         gboolean retVal = FALSE;
287         struct stat filestat;
288         if( path ) {
289                 if( 0 == lstat( path, &filestat ) ) {
290                         cache->modifyTime = filestat.st_mtime;
291                         retVal = TRUE;
292                 }
293         }
294         return retVal;
295 }
296
297 /*
298 * Print list of items.
299 */
300 void addrcache_print_item_list( GList *list, FILE *stream ) {
301         GList *node = list;
302         while( node ) {
303                 AddrItemObject *obj = node->data;
304                 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
305                         addritem_print_item_person( ( ItemPerson * ) obj, stream );
306                 }
307                 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
308                         addritem_print_item_group( ( ItemGroup * ) obj, stream );
309                 }
310                 else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
311                         addritem_print_item_folder( ( ItemFolder * ) obj, stream );
312                 }
313                 node = g_list_next( node );
314         }
315         fprintf( stream, "\t---\n" );
316 }
317
318 /*
319 * Print item hash table visitor function.
320 */
321 static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
322         AddrItemObject *obj = ( AddrItemObject * ) value;
323         FILE *stream = ( FILE * ) data;
324         if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
325                 addritem_print_item_person( ( ItemPerson * ) obj, stream );
326         }
327         else if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
328                 printf( "addrcache: print email\n" );
329         }
330         else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
331                 addritem_print_item_group( ( ItemGroup * ) obj, stream );
332         }
333         else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
334                 addritem_print_item_folder( ( ItemFolder * ) obj, stream );
335         }
336 }
337
338 /*
339 * Dump entire address cache hash table contents.
340 */
341 void addrcache_print( AddressCache *cache, FILE *stream ) {
342         g_return_if_fail( cache != NULL );
343         fprintf( stream, "AddressCache:\n" );
344         fprintf( stream, "cache id : %s\n",  cache->cacheID );
345         fprintf( stream, "next id  : %d\n",  cache->nextID );
346         fprintf( stream, "name     : %s\n",  cache->name );
347         fprintf( stream, "mod time : %ld\n", cache->modifyTime );
348         fprintf( stream, "modified : %s\n",  cache->modified ? "yes" : "no" );
349         fprintf( stream, "data read: %s\n",  cache->dataRead ? "yes" : "no" );
350 }
351
352 /*
353 * Dump entire address cache hash table contents.
354 */
355 void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
356         g_return_if_fail( cache != NULL );
357         addrcache_print( cache, stream );
358         g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
359 }
360
361 /*
362  * Allocate ID for person.
363  */
364 void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
365         g_return_if_fail( cache != NULL );
366         g_return_if_fail( person != NULL );
367         if( ADDRITEM_ID(person) ) return;
368         addrcache_next_id( cache );
369         ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
370 }
371
372 /*
373  * Allocate ID for group.
374  */
375 void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
376         g_return_if_fail( cache != NULL );
377         g_return_if_fail( group != NULL );
378         if( ADDRITEM_ID(group) ) return;
379         addrcache_next_id( cache );
380         ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
381 }
382
383 /*
384  * Allocate ID for folder.
385  */
386 void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
387         g_return_if_fail( cache != NULL );
388         g_return_if_fail( folder != NULL );
389         if( ADDRITEM_ID(folder) ) return;
390         addrcache_next_id( cache );
391         ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
392 }
393
394 /*
395  * Allocate ID for email address.
396  */
397 void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
398         g_return_if_fail( cache != NULL );
399         g_return_if_fail( email != NULL );
400         if( ADDRITEM_ID(email) ) return;
401         addrcache_next_id( cache );
402         ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
403 }
404
405 /*
406  * Allocate ID for user attribute.
407  */
408 void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
409         g_return_if_fail( cache != NULL );
410         g_return_if_fail( attrib != NULL );
411         if( attrib->uid ) return;
412         addrcache_next_id( cache );
413         attrib->uid = g_strdup_printf( "%d", cache->nextID );
414 }
415
416 /*
417 * Add person to hash table.
418 * return: TRUE if item added.
419 */
420 gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
421         if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
422                 return FALSE;
423         }
424         g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
425         return TRUE;
426 }
427
428 /*
429 * Add email to hash table.
430 * return: TRUE if item added.
431 */
432 gboolean addrcache_hash_add_email( AddressCache *cache, ItemEMail *email ) {
433         if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(email) ) ) {
434                 return FALSE;
435         }
436         g_hash_table_insert( cache->itemHash, ADDRITEM_ID(email), email );
437         return TRUE;
438 }
439
440 /*
441 * Add group to hash table.
442 * return: TRUE if item added.
443 */
444 gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
445         g_return_val_if_fail( cache != NULL, FALSE );
446         g_return_val_if_fail( group != NULL, FALSE );
447
448         if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
449                 return FALSE;
450         }
451         g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
452         return TRUE;
453 }
454
455 /*
456 * Add folder to hash table.
457 * return: TRUE if item added.
458 */
459 gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
460         g_return_val_if_fail( cache != NULL, FALSE );
461         g_return_val_if_fail( folder != NULL, FALSE );
462
463         if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
464                 return FALSE;
465         }
466         g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
467         return TRUE;
468 }
469
470 /*
471 * Add person to specified folder in cache.
472 */
473 gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
474         gboolean retVal = FALSE;
475
476         g_return_val_if_fail( cache != NULL, FALSE );
477         g_return_val_if_fail( folder != NULL, FALSE );
478         g_return_val_if_fail( item != NULL, FALSE );
479
480         retVal = addrcache_hash_add_person( cache, item );
481         if( retVal ) {
482                 addritem_folder_add_person( folder, item );
483                 cache->dirtyFlag = TRUE;
484         }
485         return retVal;
486 }
487
488 /*
489 * Add folder to specified folder in cache.
490 */
491 gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
492         gboolean retVal = FALSE;
493
494         g_return_val_if_fail( cache != NULL, FALSE );
495         g_return_val_if_fail( folder != NULL, FALSE );
496         g_return_val_if_fail( item != NULL, FALSE );
497
498         retVal = addrcache_hash_add_folder( cache, item );
499         if( retVal ) {
500                 addritem_folder_add_folder( folder, item );
501                 cache->dirtyFlag = TRUE;
502         }
503         return TRUE;
504 }
505
506 /*
507 * Add folder to specified folder in cache.
508 */
509 gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
510         gboolean retVal = FALSE;
511
512         g_return_val_if_fail( cache != NULL, FALSE );
513         g_return_val_if_fail( folder != NULL, FALSE );
514         g_return_val_if_fail( item != NULL, FALSE );
515
516         retVal = addrcache_hash_add_group( cache, item );
517         if( retVal ) {
518                 addritem_folder_add_group( folder, item );
519                 cache->dirtyFlag = TRUE;
520         }
521         return retVal;
522 }
523
524 /*
525 * Add person to address cache.
526 * return: TRUE if item added.
527 */
528 gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
529         gboolean retVal = FALSE;
530
531         g_return_val_if_fail( cache != NULL, FALSE );
532         g_return_val_if_fail( person != NULL, FALSE );
533
534         retVal = addrcache_hash_add_person( cache, person );
535         if( retVal ) {
536                 addritem_folder_add_person( cache->rootFolder, person );
537                 cache->dirtyFlag = TRUE;
538         }
539         return retVal;
540 }
541
542 /*
543 * Add EMail address to person.
544 * return: TRUE if item added.
545 */
546 gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
547         gboolean retVal = FALSE;
548
549         g_return_val_if_fail( cache != NULL, FALSE );
550         g_return_val_if_fail( person != NULL, FALSE );
551         g_return_val_if_fail( email != NULL, FALSE );
552
553         retVal = addrcache_hash_add_email( cache, email );
554         if( retVal ) {
555                 addritem_person_add_email( person, email );
556                 cache->dirtyFlag = TRUE;
557         }
558         return retVal;
559 }
560
561 /*
562 * Add group to address cache.
563 * return: TRUE if item added.
564 */
565 gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
566         gboolean retVal = FALSE;
567
568         g_return_val_if_fail( cache != NULL, FALSE );
569         g_return_val_if_fail( group != NULL, FALSE );
570
571         retVal = addrcache_hash_add_group( cache, group );
572         if( retVal ) {
573                 addritem_folder_add_group( cache->rootFolder, group );
574                 cache->dirtyFlag = TRUE;
575         }
576         return retVal;
577 }
578
579 /*
580 * Add EMail address to person.
581 * return: TRUE if item added.
582 */
583 gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
584         g_return_val_if_fail( cache != NULL, FALSE );
585         g_return_val_if_fail( group != NULL, FALSE );
586         g_return_val_if_fail( email != NULL, FALSE );
587
588         addritem_group_add_email( group, email );
589         cache->dirtyFlag = TRUE;
590         return TRUE;
591 }
592
593 /*
594 * Add folder to address cache.
595 * return: TRUE if item added.
596 */
597 gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
598         gboolean retVal = FALSE;
599
600         g_return_val_if_fail( cache != NULL, FALSE );
601         g_return_val_if_fail( folder != NULL, FALSE );
602
603         retVal = addrcache_hash_add_folder( cache, folder );
604         if( retVal ) {
605                 addritem_folder_add_folder( cache->rootFolder, folder );
606                 cache->dirtyFlag = TRUE;
607         }
608         return retVal;
609 }
610
611 /*
612 * Move person to destination folder.
613 * Enter: cache  Cache.
614 *        person Person to move.
615 *        target Target folder.
616 */
617 void addrcache_folder_move_person(
618         AddressCache *cache, ItemPerson *person, ItemFolder *target )
619 {
620         ItemFolder *parent;
621
622         g_return_if_fail( cache != NULL );
623         g_return_if_fail( person != NULL );
624
625         parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
626         if( ! parent ) parent = cache->rootFolder;
627         parent->listPerson = g_list_remove( parent->listPerson, person );
628         target->listPerson = g_list_append( target->listPerson, person );
629         ADDRITEM_PARENT(person) = ADDRITEM_OBJECT(target);
630         cache->dirtyFlag = TRUE;
631 }
632
633 /*
634 * Move group to destination folder.
635 * Enter: cache  Cache.
636 *        group  Group to move.
637 *        target Target folder.
638 */
639 void addrcache_folder_move_group(
640         AddressCache *cache, ItemGroup *group, ItemFolder *target )
641 {
642         ItemFolder *parent;
643
644         g_return_if_fail( cache != NULL );
645         g_return_if_fail( group != NULL );
646
647         parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
648         if( ! parent ) parent = cache->rootFolder;
649         parent->listGroup = g_list_remove( parent->listGroup, group );
650         target->listGroup = g_list_append( target->listGroup, group );
651         ADDRITEM_PARENT(group) = ADDRITEM_OBJECT(target);
652         cache->dirtyFlag = TRUE;
653 }
654
655 /*
656 * Move folder to destination folder.
657 * Enter: cache  Cache.
658 *        folder Folder to move.
659 *        target Target folder.
660 */
661 void addrcache_folder_move_folder(
662         AddressCache *cache, ItemFolder *folder, ItemFolder *target )
663 {
664         ItemFolder *parent;
665
666         g_return_if_fail( cache != NULL );
667         g_return_if_fail( folder != NULL );
668
669         parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
670         if( ! parent ) parent = cache->rootFolder;
671         parent->listFolder = g_list_remove( parent->listFolder, folder );
672         target->listFolder = g_list_append( target->listFolder, folder );
673         ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(target);
674         cache->dirtyFlag = TRUE;
675 }
676
677 /*
678 * Return pointer to object (either person or group) for specified ID.
679 * param: uid Object ID.
680 * return: Object, or NULL if not found.
681 */
682 AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
683         AddrItemObject *obj = NULL;
684         gchar *uidH;
685
686         g_return_val_if_fail( cache != NULL, NULL );
687
688         if( uid == NULL || *uid == '\0' ) return NULL;
689         obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
690         if( obj ) {
691                 /* Check for matching UID */
692                 uidH = ADDRITEM_ID(obj);
693                 if( uidH ) {
694                         if( strcmp( uidH, uid ) == 0 ) return obj;
695                 }
696         }
697         return NULL;
698 }
699
700 /*
701 * Return pointer for specified object ID.
702 * param: uid Object ID.
703 * return: Person object, or NULL if not found.
704 */
705 ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
706         ItemPerson *person = NULL;
707         AddrItemObject *obj = addrcache_get_object( cache, uid );
708
709         if( obj ) {
710                 if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
711                         person = ( ItemPerson * ) obj;
712                 }
713         }
714         return person;
715 }
716
717 /*
718 * Return pointer for specified object ID.
719 * param: uid group ID.
720 * return: Group object, or NULL if not found.
721 */
722 ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
723         ItemGroup *group = NULL;
724         AddrItemObject *obj = addrcache_get_object( cache, uid );
725
726         if( obj ) {
727                 if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
728                         group = ( ItemGroup * ) obj;
729                 }
730         }
731         return group;
732 }
733
734 /*
735 * Find email address in address cache.
736 * param: eid    EMail ID.
737 * return: email object for specified object ID and email ID, or NULL if not found.
738 */
739 ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *eid ) {
740         ItemEMail *email = NULL;
741         AddrItemObject *obj = addrcache_get_object( cache, eid );
742
743         if( obj ) {
744                 if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
745                         email = ( ItemEMail * ) obj;
746                 }
747         }
748         return email;
749 }
750
751 /*
752 * Remove attribute from person.
753 * param: uid    Object ID for person.
754 *        aid    Attribute ID.
755 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
756 */
757 UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
758         UserAttribute *attrib = NULL;
759         ItemPerson *person;
760
761         if( aid == NULL || *aid == '\0' ) return NULL;
762
763         person = addrcache_get_person( cache, uid );
764         if( person ) {
765                 attrib = addritem_person_remove_attrib_id( person, aid );
766                 cache->dirtyFlag = TRUE;
767         }
768         return attrib;
769 }
770
771 /*
772 * Remove attribute from person.
773 * param: person Person.
774 *        attrib Attribute to remove.
775 * return: UserAttribute object. Note that object should still be freed.
776 */
777 UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
778         UserAttribute *found = NULL;
779
780         g_return_val_if_fail( cache != NULL, NULL );
781
782         if( person && attrib ) {
783                 found = addritem_person_remove_attribute( person, attrib );
784                 cache->dirtyFlag = TRUE;
785         }
786         return found;
787 }
788
789 /*
790 * Remove group from address cache.
791 * param: group  Group to remove.
792 * return: Group, or NULL if not found. Note that object should still be freed.
793 */
794 ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
795         AddrItemObject *obj = NULL;
796
797         g_return_val_if_fail( cache != NULL, NULL );
798
799         if( group ) {
800                 gchar *uid = ADDRITEM_ID(group);
801                 if( uid == NULL || *uid == '\0' ) return NULL;
802                 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
803                 if( obj ) {
804                         ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
805                         if( ! parent ) parent = cache->rootFolder;
806
807                         /* Remove group from parent's list and hash table */
808                         parent->listGroup = g_list_remove( parent->listGroup, obj );
809                         g_hash_table_remove( cache->itemHash, uid );
810                         cache->dirtyFlag = TRUE;
811                         return group;
812                 }
813         }
814         return NULL;
815 }
816
817 /*
818 * Remove specified email from address cache. Note that object is only
819 * removed from cache and not parent objects.
820 * param: email  EMail to remove.
821 * return: EMail, or NULL if not found. Note that object should still be freed.
822 */
823 ItemEMail *addrcache_remove_email( AddressCache *cache, ItemEMail *email ) {
824         AddrItemObject *obj = NULL;
825
826         g_return_val_if_fail( cache != NULL, NULL );
827
828         if( email ) {
829                 gchar *eid = ADDRITEM_ID(email);
830                 if( eid == NULL || *eid == '\0' ) return NULL;
831                 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, eid );
832                 if( obj ) {
833                         if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
834                                 /* Remove email addresses from hash table. */
835                                 g_hash_table_remove( cache->itemHash, eid );
836                                 cache->dirtyFlag = TRUE;
837                                 return email;
838                         }
839                 }
840         }
841         return NULL;
842 }
843
844 /*
845 * Hash table visitor function to remove email from group.
846 */
847 static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
848         AddrItemObject *obj = ( AddrItemObject * ) value;
849         ItemEMail *email = ( ItemEMail * ) data;
850
851         if( ! email ) return;
852         if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
853                 ItemGroup *group = ( ItemGroup * ) value;
854                 if( group ) {
855                         /* Remove each email address that belongs to the person from the list */
856                         group->listEMail = g_list_remove( group->listEMail, email );
857                 }
858         }
859 }
860
861 /*
862 * Remove specified person from address cache.
863 * param: person Person to remove.
864 * return: Person, or NULL if not found. Note that object should still be freed.
865 */
866 ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
867         AddrItemObject *obj = NULL;
868         gchar *uid;
869
870         g_return_val_if_fail( cache != NULL, NULL );
871
872         if( person ) {
873                 uid = ADDRITEM_ID(person);
874                 if( uid == NULL || *uid == '\0' ) return NULL;
875                 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
876                 if( obj ) {
877                         if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
878                                 ItemFolder *parent;
879                                 GList *node;
880
881                                 /* Remove all email addresses for person */
882                                 /* from groups and from hash table */
883                                 node = person->listEMail;
884                                 while( node ) {
885                                         ItemEMail *email;
886                                         gchar *eid;
887
888                                         email = node->data;
889                                         g_hash_table_foreach( cache->itemHash,
890                                                 addrcache_allgrp_rem_email_vis, email );
891                                         eid = ADDRITEM_ID( email );
892                                         g_hash_table_remove( cache->itemHash, eid );
893                                         node = g_list_next( node );
894                                 }
895
896                                 /* Remove person from owning folder */
897                                 parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
898                                 if( ! parent ) parent = cache->rootFolder;
899                                 parent->listPerson = g_list_remove( parent->listPerson, person );
900                                 g_hash_table_remove( cache->itemHash, uid );
901                                 cache->dirtyFlag = TRUE;
902                                 return person;
903                         }
904                 }
905         }
906         return NULL;
907 }
908
909 /*
910 * Remove email address in address cache for specified person.
911 * param: person Person.
912 *        email  EMail to remove.
913 * return: EMail object, or NULL if not found. Note that object should still be freed.
914 */
915 ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
916         ItemEMail *found = NULL;
917
918         g_return_val_if_fail( cache != NULL, NULL );
919
920         if( person && email ) {
921                 found = addritem_person_remove_email( person, email );
922                 if( found ) {
923                         /* Remove email from all groups. */
924                         g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
925
926                         /* Remove email from person's address list */
927                         if( person->listEMail ) {
928                                 person->listEMail = g_list_remove( person->listEMail, email );
929                         }
930                         /* Unlink reference to person. */
931                         ADDRITEM_PARENT(email) = NULL;
932                         cache->dirtyFlag = TRUE;
933                 }
934         }
935         return found;
936 }
937
938 /*
939 * Move email address in address cache to new person. If member of group, address
940 * remains in group.
941 * param: cache  Cache.
942 *        email  EMail to remove.
943 *        target Target person.
944 * return: EMail object, or NULL if not found. Note that object should still be freed.
945 */
946 void addrcache_person_move_email(
947         AddressCache *cache, ItemEMail *email, ItemPerson *target )
948 {
949         ItemPerson *person;
950
951         g_return_if_fail( cache != NULL );
952
953         if( email == NULL ) return;
954         if( target == NULL ) return;
955
956         person = ( ItemPerson * ) ADDRITEM_PARENT(email);
957         if( person ) {
958                 ItemEMail *found;
959                 found = addritem_person_remove_email( person, email );
960                 if( found ) {
961                         /*
962                         if( person->listEMail ) {
963                                 person->listEMail = g_list_remove( person->listEMail, found );
964                                 addritem_person_add_email( target, found );
965                                 cache->dirtyFlag = TRUE;
966                         }
967                         */
968                         addritem_person_add_email( target, found );
969                         cache->dirtyFlag = TRUE;
970                 }
971         }
972 }
973
974 /*
975 * Return link list of address items for root level folder. Note that the list contains
976 * references to items and should be g_free() when done. Do *NOT* attempt to use the
977 * addrcache_free_xxx() functions... this will destroy the address cache data!
978 * Return: List of items, or NULL if none.
979 */
980 GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
981         GList *list = NULL;
982         GList *node = NULL;
983         ItemFolder *f = folder;
984
985         g_return_val_if_fail( cache != NULL, NULL );
986
987         if( ! f ) f = cache->rootFolder;
988         node = f->listPerson;
989         while( node ) {
990                 list = g_list_append( list, node->data );
991                 node = g_list_next( node );
992         }
993         node = f->listGroup;
994         while( node ) {
995                 list = g_list_append( list, node->data );
996                 node = g_list_next( node );
997         }
998         return list;
999 }
1000
1001 /*
1002 * Return link list of persons for specified folder. Note that the list contains
1003 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1004 * addrcache_free_xxx() functions... this will destroy the address cache data!
1005 * Return: List of items, or NULL if none.
1006 */
1007 GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
1008         ItemFolder *f = folder;
1009
1010         g_return_val_if_fail( cache != NULL, NULL );
1011
1012         if( ! f ) f = cache->rootFolder;
1013         return addritem_folder_get_person_list( f );
1014 }
1015
1016 /*
1017 * Return link list of group items for specified folder. Note that the list contains
1018 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1019 * addrcache_free_xxx() functions... this will destroy the address cache data!
1020 * Return: List of items, or NULL if none.
1021 */
1022 GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
1023         ItemFolder *f = folder;
1024
1025         g_return_val_if_fail( cache != NULL, NULL );
1026
1027         if( ! f ) f = cache->rootFolder;
1028         return addritem_folder_get_group_list( f );
1029 }
1030
1031 /*
1032 * Return link list of folder items for specified folder. Note that the list contains
1033 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1034 * addrcache_free_xxx() functions... this will destroy the address cache data!
1035 * Return: List of items, or NULL if none.
1036 */
1037 GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
1038         GList *node = NULL;
1039         GList *list = NULL;
1040         ItemFolder *f = folder;
1041
1042         g_return_val_if_fail( cache != NULL, NULL );
1043
1044         if( ! f ) f = cache->rootFolder;
1045         node = f->listFolder;
1046         while( node ) {
1047                 list = g_list_append( list, node->data );
1048                 node = g_list_next( node );
1049         }
1050         return list;
1051 }
1052
1053 /*
1054 * Return link list of address items for root level folder. Note that the list contains
1055 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1056 * addrcache_free_xxx() functions... this will destroy the address cache data!
1057 * Return: List of items, or NULL if none.
1058 */
1059 GList *addrcache_get_address_list( AddressCache *cache ) {
1060         g_return_val_if_fail( cache != NULL, NULL );
1061         return addrcache_folder_get_address_list( cache, cache->rootFolder );
1062 }
1063
1064 /*
1065 * Return link list of persons for root level folder. Note that the list contains
1066 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1067 * addrcache_free_xxx() functions... this will destroy the address cache data!
1068 * Return: List of items, or NULL if none.
1069 */
1070 GList *addrcache_get_person_list( AddressCache *cache ) {
1071         g_return_val_if_fail( cache != NULL, NULL );
1072         return addritem_folder_get_person_list( cache->rootFolder );
1073 }
1074
1075 /*
1076 * Return link list of group items in root level folder. Note that the list contains
1077 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1078 * addrcache_free_xxx() functions... this will destroy the address cache data!
1079 * Return: List of items, or NULL if none.
1080 */
1081 GList *addrcache_get_group_list( AddressCache *cache ) {
1082         g_return_val_if_fail( cache != NULL, NULL );
1083         return cache->rootFolder->listGroup;
1084 }
1085
1086 /*
1087 * Return link list of folder items in root level folder. Note that the list contains
1088 * references to items and should be g_free() when done. Do *NOT* attempt to used the
1089 * addrcache_free_xxx() functions... this will destroy the address cache data!
1090 * Return: List of items, or NULL if none.
1091 */
1092 GList *addrcache_get_folder_list( AddressCache *cache ) {
1093         g_return_val_if_fail( cache != NULL, NULL );
1094         return cache->rootFolder->listFolder;
1095 }
1096
1097 /*
1098 * Group visitor function.
1099 */
1100 static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
1101         AddrItemObject *obj = ( AddrItemObject * ) value;
1102
1103         if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1104                 AddressCache *cache = data;
1105                 ItemGroup *group = ( ItemGroup * ) obj;
1106                 ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
1107                 GList *node = group->listEMail;
1108                 while( node ) {
1109                         ItemEMail *email = ( ItemEMail * ) node->data;
1110                         if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
1111                                 if( ! g_list_find( cache->tempList, group ) ) {
1112                                         cache->tempList = g_list_append( cache->tempList, group );
1113                                 }
1114                         }
1115                         node = g_list_next( node );
1116                 }
1117         }
1118 }
1119
1120 /*
1121 * Return linked list of groups which contain a reference to specified person's email
1122 * address.
1123 */
1124 GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
1125         GList *list = NULL;
1126
1127         g_return_val_if_fail( cache != NULL, NULL );
1128
1129         cache->tempList = NULL;
1130         cache->tempList = g_list_append( cache->tempList, person );
1131         g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
1132         cache->tempList = g_list_remove( cache->tempList, person );
1133         list = cache->tempList;
1134         cache->tempList = NULL;
1135         return list;
1136 }
1137
1138 /*
1139 * Find root folder for specified folder.
1140 * Enter: folder Folder to search.
1141 * Return: root folder, or NULL if not found.
1142 */
1143 ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1144         ItemFolder *item = folder;
1145         gint count = 0;
1146
1147         while( item ) {
1148                 if( item->isRoot ) break;
1149                 if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1150                         item = NULL;
1151                         break;
1152                 }
1153                 item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1154         }
1155         return item;
1156 }
1157
1158 /*
1159 * Get all person visitor function.
1160 */
1161 static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1162         AddrItemObject *obj = ( AddrItemObject * ) value;
1163
1164         if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1165                 AddressCache *cache = data;
1166                 cache->tempList = g_list_append( cache->tempList, obj );
1167         }
1168 }
1169
1170 /*
1171 * Return link list of all persons in address cache.  Note that the list contains
1172 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1173 * this will destroy the address cache data!
1174 * Return: List of items, or NULL if none.
1175 */
1176 GList *addrcache_get_all_persons( AddressCache *cache ) {
1177         GList *list = NULL;
1178
1179         g_return_val_if_fail( cache != NULL, NULL );
1180
1181         cache->tempList = NULL;
1182         g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1183         list = cache->tempList;
1184         cache->tempList = NULL;
1185         return list;
1186 }
1187
1188 /*
1189 * Get all groups visitor function.
1190 */
1191 static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1192         AddrItemObject *obj = ( AddrItemObject * ) value;
1193
1194         if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1195                 AddressCache *cache = data;
1196                 cache->tempList = g_list_append( cache->tempList, obj );
1197         }
1198 }
1199
1200 /*
1201 * Return link list of all groups in address cache.  Note that the list contains
1202 * references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1203 * this will destroy the address cache data!
1204 * Return: List of items, or NULL if none.
1205 */
1206 GList *addrcache_get_all_groups( AddressCache *cache ) {
1207         GList *list = NULL;
1208
1209         g_return_val_if_fail( cache != NULL, NULL );
1210
1211         cache->tempList = NULL;
1212         g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1213         list = cache->tempList;
1214         cache->tempList = NULL;
1215         return list;
1216 }
1217
1218 /*
1219 * Remove folder from cache. Children are re-parented to parent folder.
1220 * param: folder Folder to remove.
1221 * return: Folder, or NULL if not found. Note that object should still be freed.
1222 */
1223 ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1224         AddrItemObject *obj = NULL;
1225
1226         g_return_val_if_fail( cache != NULL, NULL );
1227
1228         if( folder ) {
1229                 gchar *uid = ADDRITEM_ID(folder);
1230                 if( uid == NULL || *uid == '\0' ) return NULL;
1231                 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1232                 if( obj ) {
1233                         ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1234                         GList *node;
1235                         AddrItemObject *aio;
1236                         if( ! parent ) parent = cache->rootFolder;
1237
1238                         /* Re-parent children in folder */
1239                         node = folder->listFolder;
1240                         while( node ) {
1241                                 aio = ( AddrItemObject * ) node->data;
1242                                 parent->listFolder = g_list_append( parent->listFolder, aio );
1243                                 aio->parent = ADDRITEM_OBJECT(parent);
1244                                 node = g_list_next( node );
1245                         }
1246                         node = folder->listPerson;
1247                         while( node ) {
1248                                 aio = ( AddrItemObject * ) node->data;
1249                                 parent->listPerson = g_list_append( parent->listPerson, aio );
1250                                 aio->parent = ADDRITEM_OBJECT(parent);
1251                                 node = g_list_next( node );
1252                         }
1253                         node = folder->listGroup;
1254                         while( node ) {
1255                                 aio = ( AddrItemObject * ) node->data;
1256                                 parent->listGroup = g_list_append( parent->listGroup, aio );
1257                                 aio->parent = ADDRITEM_OBJECT(parent);
1258                                 node = g_list_next( node );
1259                         }
1260
1261                         /* Remove folder from parent's list and hash table */
1262                         parent->listFolder = g_list_remove( parent->listFolder, folder );
1263                         ADDRITEM_PARENT(folder) = NULL;
1264                         g_hash_table_remove( cache->itemHash, uid );
1265                         cache->dirtyFlag = TRUE;
1266                         return folder;
1267                 }
1268         }
1269         return NULL;
1270 }
1271
1272 /*
1273 * Remove folder from cache. Children are deleted.
1274 * param: folder Folder to remove.
1275 * return: Folder, or NULL if not found. Note that object should still be freed.
1276 */
1277 ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1278         AddrItemObject *obj = NULL;
1279
1280         g_return_val_if_fail( cache != NULL, NULL );
1281
1282         if( folder ) {
1283                 gchar *uid = ADDRITEM_ID(folder);
1284                 if( uid == NULL || *uid == '\0' ) return NULL;
1285                 obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1286                 if( obj ) {
1287                         ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1288                         if( ! parent ) parent = cache->rootFolder;
1289
1290                         /* Remove groups */
1291                         while( folder->listGroup ) {
1292                                 ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1293                                 item = addrcache_remove_group( cache, item );
1294                                 if( item ) {
1295                                         addritem_free_item_group( item );
1296                                         item = NULL;
1297                                 }
1298                         }
1299
1300                         while( folder->listPerson ) {
1301                                 ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1302                                 item = addrcache_remove_person( cache, item );
1303                                 if( item ) {
1304                                         addritem_free_item_person( item );
1305                                         item = NULL;
1306                                 }
1307                         }
1308
1309                         /* Recursive deletion of folder */
1310                         while( folder->listFolder ) {
1311                                 ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1312                                 item = addrcache_remove_folder_delete( cache, item );
1313                                 if( item ) {
1314                                         addritem_free_item_folder( item );
1315                                         item = NULL;
1316                                 }
1317                         }
1318
1319                         /* Remove folder from parent's list and hash table */
1320                         parent->listFolder = g_list_remove( parent->listFolder, folder );
1321                         ADDRITEM_PARENT(folder) = NULL;
1322                         g_hash_table_remove( cache->itemHash, uid );
1323                         cache->dirtyFlag = TRUE;
1324                         return folder;
1325                 }
1326         }
1327         return NULL;
1328 }
1329
1330 /*
1331 * Add person and address data to cache.
1332 * Enter: cache     Cache.
1333 *        folder    Folder where to add person, or NULL for root folder.
1334 *        name      Common name.
1335 *        address   EMail address.
1336 *        remarks   Remarks.
1337 * Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1338 * this will destroy the address book data.
1339 */
1340 ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1341                 const gchar *address, const gchar *remarks )
1342 {
1343         ItemPerson *person = NULL;
1344         ItemEMail *email = NULL;
1345         ItemFolder *f = folder;
1346
1347         g_return_val_if_fail( cache != NULL, NULL );
1348
1349         if( ! f ) f = cache->rootFolder;
1350
1351         /* Create person object */
1352         person = addritem_create_item_person();
1353         addritem_person_set_common_name( person, name );
1354         addrcache_id_person( cache, person );
1355         addrcache_folder_add_person( cache, f, person );
1356
1357         /* Create email object */
1358         email = addritem_create_item_email();
1359         addritem_email_set_address( email, address );
1360         addritem_email_set_remarks( email, remarks );
1361         addrcache_id_email( cache, email );
1362         addritem_person_add_email( person, email );
1363         cache->dirtyFlag = TRUE;
1364
1365         return person;
1366 }
1367
1368 /*
1369 * End of Source.
1370 */