820e2e63c69f922e2aa5e14728ff066c452229ce
[claws.git] / src / addritem.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  * General primitive address item objects.
22  */
23
24 #include <glib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "addritem.h"
29 #include "mgutils.h"
30
31 /*
32 * Create new email address item.
33 */
34 ItemEMail *addritem_create_item_email( void ) {
35         ItemEMail *item;
36         item = g_new0( ItemEMail, 1 );
37         ADDRITEM_TYPE(item) = ITEMTYPE_EMAIL;
38         ADDRITEM_ID(item) = NULL;
39         ADDRITEM_NAME(item) = NULL;
40         ADDRITEM_PARENT(item) = NULL;
41         ADDRITEM_SUBTYPE(item) = 0;
42         item->address = NULL;
43         item->remarks = NULL;
44         return item;
45 }
46
47 /*
48 * Create a shallow copy of specified email address item.
49 * Enter: item E-Mail to copy.
50 */
51 ItemEMail *addritem_copy_item_email( ItemEMail *item ) {
52         ItemEMail *itemNew = NULL;
53         if( item ) {
54                 itemNew = addritem_create_item_email();
55                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
56                 itemNew->address = g_strdup( item->address );
57                 itemNew->remarks = g_strdup( item->remarks );
58         }
59         return itemNew;
60 }
61
62 /*
63 * Create a full copy of specified email address item.
64 * Enter: item E-Mail to copy.
65 */
66 ItemEMail *addritem_copyfull_item_email( ItemEMail *item ) {
67         ItemEMail *itemNew = NULL;
68         if( item ) {
69                 itemNew = addritem_create_item_email();
70                 ADDRITEM_ID(itemNew) = g_strdup( ADDRITEM_ID(item) );
71                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
72                 ADDRITEM_PARENT(itemNew) = ADDRITEM_PARENT(item);
73                 itemNew->address = g_strdup( item->address );
74                 itemNew->remarks = g_strdup( item->remarks );
75         }
76         return itemNew;
77 }
78
79 void addritem_email_set_id( ItemEMail *email, const gchar *value ) {
80         ADDRITEM_ID(email) = mgu_replace_string( ADDRITEM_ID(email), value );
81 }
82 void addritem_email_set_alias( ItemEMail *email, const gchar *value ) {
83         ADDRITEM_NAME(email) = mgu_replace_string( ADDRITEM_NAME(email), value );
84 }
85 void addritem_email_set_address( ItemEMail *email, const gchar *value ) {
86         email->address = mgu_replace_string( email->address, value );
87 }
88 void addritem_email_set_remarks( ItemEMail *email, const gchar *value ) {
89         email->remarks = mgu_replace_string( email->remarks, value );
90 }
91
92 /*
93 * Free address item email.
94 */
95 void addritem_free_item_email( ItemEMail *item ) {
96         g_return_if_fail( item != NULL );
97
98         /* Free internal stuff */
99         g_free( ADDRITEM_ID(item) );
100         g_free( ADDRITEM_NAME(item) );
101         g_free( item->address );
102         g_free( item->remarks );
103
104         ADDRITEM_OBJECT(item)->type = ITEMTYPE_NONE;
105         ADDRITEM_ID(item) = NULL;
106         ADDRITEM_NAME(item) = NULL;
107         ADDRITEM_PARENT(item) = NULL;
108         ADDRITEM_SUBTYPE(item) = 0;
109         item->address = NULL;
110         item->remarks = NULL;
111         g_free( item );
112 }
113
114 /*
115 * Create new attribute.
116 */
117 UserAttribute *addritem_create_attribute( void ) {
118         UserAttribute *item;
119         item = g_new0( UserAttribute, 1 );
120         item->uid = NULL;
121         item->name = NULL;
122         item->value = NULL;
123         return item;
124 }
125
126 /*
127 * Create copy of specified attribute.
128 */
129 UserAttribute *addritem_copy_attribute( UserAttribute *item ) {
130         UserAttribute *itemNew = NULL;
131         if( item ) {
132                 itemNew = addritem_create_attribute();
133                 itemNew->uid = g_strdup( item->uid );
134                 itemNew->name = g_strdup( item->name );
135                 itemNew->value = g_strdup( item->value );
136         }
137         return itemNew;
138 }
139
140 void addritem_attrib_set_id( UserAttribute *item, const gchar *value ) {
141         g_return_if_fail( item != NULL );
142         item->uid = mgu_replace_string( item->uid, value );
143 }
144 void addritem_attrib_set_name( UserAttribute *item, const gchar *value ) {
145         g_return_if_fail( item != NULL );
146         item->name = mgu_replace_string( item->name, value );
147 }
148 void addritem_attrib_set_value( UserAttribute *item, const gchar *value ) {
149         g_return_if_fail( item != NULL );
150         item->value = mgu_replace_string( item->value, value );
151 }
152
153 /*
154 * Free user attribute.
155 */
156 void addritem_free_attribute( UserAttribute *item ) {
157         g_return_if_fail( item != NULL );
158         g_free( item->uid );
159         g_free( item->name );
160         g_free( item->value );
161         item->uid = NULL;
162         item->name = NULL;
163         item->value = NULL;
164         g_free( item );
165 }
166
167 /*
168 * Create new address book person.
169 */
170 ItemPerson *addritem_create_item_person( void ) {
171         ItemPerson *person;
172         person = g_new0( ItemPerson, 1 );
173         ADDRITEM_TYPE(person) = ITEMTYPE_PERSON;
174         ADDRITEM_ID(person) = NULL;
175         ADDRITEM_NAME(person) = NULL;
176         ADDRITEM_PARENT(person) = NULL;
177         ADDRITEM_SUBTYPE(person) = 0;
178         person->firstName = NULL;
179         person->lastName = NULL;
180         person->nickName = NULL;
181         person->listEMail = NULL;
182         person->listAttrib = NULL;
183         person->externalID = NULL;
184         person->isOpened = FALSE;
185         return person;
186 }
187
188 /*
189 * Create a shallow copy of address book person.
190 * Enter: item Person to copy.
191 */
192 ItemPerson *addritem_copy_item_person( ItemPerson *item ) {
193         ItemPerson *itemNew;
194
195         itemNew = NULL;
196         if( item ) {
197                 itemNew = addritem_create_item_person();
198                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
199                 itemNew->firstName = g_strdup( item->firstName );
200                 itemNew->lastName = g_strdup( item->lastName );
201                 itemNew->nickName = g_strdup( item->nickName );
202                 itemNew->externalID = g_strdup( item->externalID );
203         }
204         return itemNew;
205 }
206
207 void addritem_person_set_id( ItemPerson *person, const gchar *value ) {
208         ADDRITEM_ID(person) = mgu_replace_string( ADDRITEM_ID(person), value );
209 }
210 void addritem_person_set_first_name( ItemPerson *person, const gchar *value ) {
211         person->firstName = mgu_replace_string( person->firstName, value );
212 }
213 void addritem_person_set_last_name( ItemPerson *person, const gchar *value ) {
214         person->lastName = mgu_replace_string( person->lastName, value );
215 }
216 void addritem_person_set_nick_name( ItemPerson *person, const gchar *value ) {
217         person->nickName = mgu_replace_string( person->nickName, value );
218 }
219 void addritem_person_set_common_name( ItemPerson *person, const gchar *value ) {
220         ADDRITEM_NAME(person) = mgu_replace_string( ADDRITEM_NAME(person), value );
221 }
222 void addritem_person_set_external_id( ItemPerson *person, const gchar *value ) {
223         person->externalID = mgu_replace_string( person->externalID, value );
224 }
225 void addritem_person_set_opened( ItemPerson *person, const gboolean value ) {
226         person->isOpened = value;
227 }
228
229 /*
230  * Test whether person's data is empty.
231  * Enter: person Person to test.
232  * Return: TRUE if empty.
233  */
234 gboolean addritem_person_empty( ItemPerson *person ) {
235         gchar *t;
236
237         if( person == NULL ) return FALSE;
238
239         t = ADDRITEM_NAME(person);
240         if( t != NULL && strlen( t ) > 0 ) return FALSE;
241
242         t = person->firstName;
243         if( t != NULL && strlen( t ) > 0 ) return FALSE;
244
245         t = person->lastName;
246         if( t != NULL && strlen( t ) > 0 ) return FALSE;
247
248         t = person->nickName;
249         if( t != NULL && strlen( t ) > 0 ) return FALSE;
250
251         if( person->listEMail  != NULL ) return FALSE;
252         if( person->listAttrib != NULL ) return FALSE;
253
254         return TRUE;
255 }
256
257 /*
258  * Free linked list of item addresses; both addresses and the list are freed.
259  * It is assumed that addresses are *NOT* contained within some other
260  * container.
261  * Enter: list List of addresses to be freed.
262  */
263 void addritem_free_list_email( GList *list ) {
264         GList *node = list;
265         while( node ) {
266                 ItemEMail *email = node->data;
267
268                 addritem_free_item_email( email );
269                 node->data = NULL;
270                 node = g_list_next( node );
271         }
272         g_list_free( list );
273         list = NULL;
274 }
275
276 /*
277 * Free linked list of attributes.
278 */
279 void addritem_free_list_attribute( GList *list ) {
280         GList *node = list;
281         while( node ) {
282                 addritem_free_attribute( node->data );
283                 node->data = NULL;
284                 node = g_list_next( node );
285         }
286         g_list_free( list );
287 }
288
289 /*
290 * Free address person.
291 */
292 void addritem_free_item_person( ItemPerson *person ) {
293         g_return_if_fail( person != NULL );
294
295         /* Free internal stuff */
296         g_free( ADDRITEM_ID(person) );
297         g_free( ADDRITEM_NAME(person) );
298         g_free( person->firstName );
299         g_free( person->lastName );
300         g_free( person->nickName );
301         g_free( person->externalID );
302         g_list_free( person->listEMail );
303         addritem_free_list_attribute( person->listAttrib );
304
305         ADDRITEM_OBJECT(person)->type = ITEMTYPE_NONE;
306         ADDRITEM_ID(person) = NULL;
307         ADDRITEM_NAME(person) = NULL;
308         ADDRITEM_PARENT(person) = NULL;
309         ADDRITEM_SUBTYPE(person) = 0;
310         person->firstName = NULL;
311         person->lastName = NULL;
312         person->nickName = NULL;
313         person->externalID = NULL;
314         person->listEMail = NULL;
315         person->listAttrib = NULL;
316
317         g_free( person );
318 }
319
320 /*
321 * Print address item.
322 */
323 void addritem_print_item_email( ItemEMail *item, FILE *stream ) {
324         g_return_if_fail( item != NULL );
325         fprintf( stream, "\t\tt/id: %d : '%s'\n", ADDRITEM_TYPE(item), ADDRITEM_ID(item) );
326         fprintf( stream, "\t\tsubty: %d\n", ADDRITEM_SUBTYPE(item) );
327         fprintf( stream, "\t\talis: '%s'\n", ADDRITEM_NAME(item) );
328         fprintf( stream, "\t\taddr: '%s'\n", item->address );
329         fprintf( stream, "\t\trems: '%s'\n", item->remarks );
330         fprintf( stream, "\t\t---\n" );
331 }
332
333 /*
334 * Print user attribute.
335 */
336 void addritem_print_attribute( UserAttribute *item, FILE *stream ) {
337         g_return_if_fail( item != NULL );
338         fprintf( stream, "\t\tuid  : '%s'\n", item->uid );
339         fprintf( stream, "\t\tname : '%s'\n", item->name );
340         fprintf( stream, "\t\tvalue: '%s'\n", item->value );
341         fprintf( stream, "\t\t---\n" );
342 }
343
344 /*
345 * Print person item.
346 */
347 void addritem_print_item_person( ItemPerson *person, FILE *stream ) {
348         GList *node;
349         g_return_if_fail( person != NULL );
350         fprintf( stream, "Person:\n" );
351         fprintf( stream, "\tt/uid: %d : '%s'\n", ADDRITEM_TYPE(person), ADDRITEM_ID(person) );
352         fprintf( stream, "\tsubty: %d\n", ADDRITEM_SUBTYPE(person) );
353         fprintf( stream, "\tcommn: '%s'\n", ADDRITEM_NAME(person) );
354         fprintf( stream, "\tfirst: '%s'\n", person->firstName );
355         fprintf( stream, "\tlast : '%s'\n", person->lastName );
356         fprintf( stream, "\tnick : '%s'\n", person->nickName );
357         fprintf( stream, "\textID: '%s'\n", person->externalID );
358         fprintf( stream, "\teMail:\n" );
359         fprintf( stream, "\t---\n" );
360         node = person->listEMail;
361         while( node ) {
362                 addritem_print_item_email( node->data, stream );
363                 node = g_list_next( node );
364         }
365         fprintf( stream, "\tuAttr:\n" );
366         fprintf( stream, "\t---\n" );
367         node = person->listAttrib;
368         while( node ) {
369                 addritem_print_attribute( node->data, stream );
370                 node = g_list_next( node );
371         }
372         fprintf( stream, "\t===\n" );
373 }
374
375 /*
376 * Add EMail address to person.
377 * return: TRUE if item added.
378 */
379 gboolean addritem_person_add_email( ItemPerson *person, ItemEMail *email ) {
380         GList *node;
381
382         g_return_val_if_fail( person != NULL, FALSE );
383         g_return_val_if_fail( email != NULL, FALSE );
384
385         node = person->listEMail;
386         while( node ) {
387                 if( node->data == email ) return FALSE;
388                 node = g_list_next( node );
389         }
390         person->listEMail = g_list_append( person->listEMail, email );
391         ADDRITEM_PARENT(email) = ADDRITEM_OBJECT(person);
392         return TRUE;
393 }
394
395 /*
396 * Return email object with specified ID.
397 * param: person Person object.
398 *        eid    EMail ID.
399 * return: EMail object, or NULL if not found.
400 */
401 ItemEMail *addritem_person_get_email( ItemPerson *person, const gchar *eid ) {
402         ItemEMail *email = NULL;
403         GList *node;
404
405         g_return_val_if_fail( person != NULL, NULL );
406         if( eid == NULL || *eid == '\0' ) return NULL;
407
408         /* Look for email */
409         node = person->listEMail;
410         while( node ) {
411                 AddrItemObject *objE = node->data;
412                 gchar *ide = ADDRITEM_ID(objE);
413                 if( ide ) {
414                         if( strcmp( ide, eid ) == 0 ) {
415                                 email = ( ItemEMail * ) objE;
416                         }
417                 }
418                 node = g_list_next( node );
419         }
420         return email;
421 }
422
423 /*
424 * Remove email address for specified person.
425 * param: person Person object.
426 *        eid    EMail ID.
427 * return: EMail object, or NULL if not found. Note that object should still be freed.
428 */
429 ItemEMail *addritem_person_remove_email_id( ItemPerson *person, const gchar *eid ) {
430         ItemEMail *email = NULL;
431         GList *node;
432
433         g_return_val_if_fail( person != NULL, NULL );
434         if( eid == NULL || *eid == '\0' ) return NULL;
435
436         /* Look for email */
437         node = person->listEMail;
438         while( node ) {
439                 AddrItemObject *objE = node->data;
440                 gchar *ide = ADDRITEM_ID(objE);
441                 if( ide ) {
442                         if( strcmp( ide, eid ) == 0 ) {
443                                 email = ( ItemEMail * ) objE;
444                         }
445                 }
446                 node = g_list_next( node );
447         }
448
449         if( email ) {
450                 /* Remove email from person's address list */
451                 if( person->listEMail ) {
452                         person->listEMail = g_list_remove( person->listEMail, email );
453                 }
454                 /* Unlink reference to person. */
455                 ADDRITEM_PARENT(email) = NULL;
456         }
457         return email;
458 }
459
460 /*
461 * Remove email address for specified.
462 * param: person Person.
463 *        email  EMail to remove.
464 * return: EMail object, or NULL if not found. Note that object should still be freed.
465 */
466 ItemEMail *addritem_person_remove_email( ItemPerson *person, ItemEMail *email ) {
467         gboolean found = FALSE;
468         GList *node;
469
470         g_return_val_if_fail( person != NULL, NULL );
471         if( email == NULL ) return NULL;
472
473         /* Look for email */
474         node = person->listEMail;
475         while( node ) {
476                 if( node-> data == email ) {
477                         found = TRUE;
478                         break;
479                 }
480                 node = g_list_next( node );
481         }
482
483         if( found ) {
484                 /* Remove email from person's address list */
485                 if( person->listEMail ) {
486                         person->listEMail = g_list_remove( person->listEMail, email );
487                 }
488                 /* Unlink reference to person. */
489                 ADDRITEM_PARENT(email) = NULL;
490                 return email;
491         }
492         return NULL;
493 }
494
495 /*
496 * Add user attribute to person.
497 * return: TRUE if item added.
498 */
499 void addritem_person_add_attribute( ItemPerson *person, UserAttribute *attrib ) {
500         g_return_if_fail( person != NULL );
501         person->listAttrib = g_list_append( person->listAttrib, attrib );
502 }
503
504 /*
505 * Return attribute with specified ID.
506 * param: person Person object.
507 *        aid    Attribute ID.
508 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
509 */
510 UserAttribute *addritem_person_get_attribute( ItemPerson *person, const gchar *aid ) {
511         UserAttribute *attrib = NULL;
512         GList *node;
513
514         g_return_val_if_fail( person != NULL, NULL );
515         if( aid == NULL || *aid == '\0' ) return NULL;
516
517         /* Look for attribute */
518         node = person->listAttrib;
519         while( node ) {
520                 UserAttribute *attr = node->data;
521                 gchar *ida = attr->uid;
522                 if( ida ) {
523                         if( strcmp( ida, aid ) == 0 ) {
524                                 attrib = attr;
525                         }
526                 }
527                 node = g_list_next( node );
528         }
529         return attrib;
530 }
531
532 /*
533 * Remove attribute from person.
534 * param: person Person object.
535 *        aid    Attribute ID.
536 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
537 */
538 UserAttribute *addritem_person_remove_attrib_id( ItemPerson *person, const gchar *aid ) {
539         UserAttribute *attrib = NULL;
540         GList *node;
541
542         g_return_val_if_fail( person != NULL, NULL );
543         if( aid == NULL || *aid == '\0' ) return NULL;
544
545         /* Look for attribute */
546         node = person->listAttrib;
547         while( node ) {
548                 UserAttribute *attr = node->data;
549                 gchar *ida = attr->uid;
550                 if( ida ) {
551                         if( strcmp( ida, aid ) == 0 ) {
552                                 attrib = attr;
553                         }
554                 }
555                 node = g_list_next( node );
556         }
557
558         /* Remove email from person's address list */
559         if( person->listAttrib ) {
560                 person->listAttrib = g_list_remove( person->listAttrib, attrib );
561         }
562         return attrib;
563 }
564
565 /*
566 * Remove attribute from person.
567 * param: person Person.
568 *        attrib Attribute to remove.
569 * return: UserAttribute object. Note that object should still be freed.
570 */
571 UserAttribute *addritem_person_remove_attribute( ItemPerson *person, UserAttribute *attrib ) {
572         gboolean found = FALSE;
573         GList *node;
574
575         g_return_val_if_fail( person != NULL, NULL );
576         if( attrib == NULL ) return NULL;
577
578         /* Look for attribute */
579         node = person->listAttrib;
580         while( node ) {
581                 if( node-> data == attrib ) {
582                         found = TRUE;
583                         break;
584                 }
585                 node = g_list_next( node );
586         }
587
588         if( found ) {
589                 /* Remove attribute */
590                 if( person->listAttrib ) {
591                         person->listAttrib = g_list_remove( person->listAttrib, attrib );
592                 }
593         }
594         return attrib;
595 }
596
597 /*
598 * Create new address book group.
599 */
600 ItemGroup *addritem_create_item_group( void ) {
601         ItemGroup *group;
602
603         group = g_new0( ItemGroup, 1 );
604         ADDRITEM_TYPE(group) = ITEMTYPE_GROUP;
605         ADDRITEM_ID(group) = NULL;
606         ADDRITEM_NAME(group) = NULL;
607         ADDRITEM_PARENT(group) = NULL;
608         ADDRITEM_SUBTYPE(group) = 0;
609         group->remarks = NULL;
610         group->listEMail = NULL;
611         return group;
612 }
613
614 /*
615 * Copy address book group.
616 * Enter:  item Group to copy.
617 * Return: A copy of the group. 
618 */
619 ItemGroup *addritem_copy_item_group( ItemGroup *item ) {
620         ItemGroup *itemNew;
621
622         itemNew = g_new0( ItemGroup, 1 );
623         if( item ) {
624                 itemNew = addritem_create_item_group();
625                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
626                 itemNew->remarks = g_strdup( item->remarks );
627         }
628         return itemNew;
629 }
630
631 /*
632 * Specify name to be used.
633 */
634 void addritem_group_set_id( ItemGroup *group, const gchar *value ) {
635         ADDRITEM_ID(group) = mgu_replace_string( ADDRITEM_ID(group), value );
636 }
637 void addritem_group_set_name( ItemGroup *group, const gchar *value ) {
638         ADDRITEM_NAME(group) = mgu_replace_string( ADDRITEM_NAME(group), value );
639 }
640 void addritem_group_set_remarks( ItemGroup *group, const gchar *value ) {
641         group->remarks = mgu_replace_string( group->remarks, value );
642 }
643
644 /*
645 * Free address group.
646 */
647 void addritem_free_item_group( ItemGroup *group ) {
648         g_return_if_fail( group != NULL );
649
650         /* Free internal stuff */
651         g_free( ADDRITEM_ID(group) );
652         g_free( ADDRITEM_NAME(group) );
653         g_free( group->remarks );
654         mgu_clear_list( group->listEMail );
655         g_list_free( group->listEMail );
656
657         ADDRITEM_TYPE(group) = ITEMTYPE_NONE;
658         ADDRITEM_ID(group) = NULL;
659         ADDRITEM_NAME(group) = NULL;
660         ADDRITEM_PARENT(group) = NULL;
661         ADDRITEM_SUBTYPE(group) = 0;
662         group->remarks = NULL;
663         group->listEMail = NULL;
664
665         g_free( group );
666 }
667
668 /*
669 * Add EMail address to group.
670 * return: TRUE if item added.
671 */
672 gboolean addritem_group_add_email( ItemGroup *group, ItemEMail *email ) {
673         GList *node;
674
675         g_return_val_if_fail( group != NULL, FALSE );
676         g_return_val_if_fail( email != NULL, FALSE );
677
678         node = group->listEMail;
679         while( node ) {
680                 if( node->data == email ) return FALSE;
681                 node = g_list_next( node );
682         }
683         group->listEMail = g_list_append( group->listEMail, email );
684         return TRUE;
685 }
686
687 /*
688 * Remove email address for specified group.
689 * param: group  Group from which to remove address.
690 *        email  EMail to remove
691 * return: EMail object, or NULL if email not found in group. Note that this object is
692 * referenced (linked) to a group and should *NOT* be freed. This object should only be
693 * freed after removing from a person.
694 */
695 ItemEMail *addritem_group_remove_email( ItemGroup *group, ItemEMail *email ) {
696         if( group && email ) {
697                 GList *node = group->listEMail;
698                 while( node ) {
699                         if( node->data == email ) {
700                                 group->listEMail = g_list_remove( group->listEMail, email );
701                                 return email;
702                         }
703                         node = g_list_next( node );
704                 }
705         }
706         return NULL;
707 }
708
709 /*
710 * Remove email address for specified group and ID.
711 * param: group  Group from which to remove address.
712 *        eid    EMail ID.
713 * return: EMail object, or NULL if email not found in group. Note that this object is
714 * referenced (linked) to a group and should *NOT* be freed. This object should only be
715 * freed after removing from a person.
716 */
717 ItemEMail *addritem_group_remove_email_id( ItemGroup *group, const gchar *eid ) {
718         if( group ) {
719                 GList *node = group->listEMail;
720                 while( node ) {
721                         ItemEMail *email = ( ItemEMail * ) node->data;
722                         if( strcmp( ADDRITEM_ID( email ), eid ) == 0 ) {
723                                 group->listEMail = g_list_remove( group->listEMail, email );
724                                 return email;
725                         }
726                         node = g_list_next( node );
727                 }
728         }
729         return NULL;
730 }
731
732 /*
733 * Print address group item.
734 */
735 void addritem_print_item_group( ItemGroup *group, FILE *stream ) {
736         GList *node;
737         ItemPerson *person;
738         ItemEMail *item;
739         g_return_if_fail( group != NULL );
740         fprintf( stream, "Group:\n" );
741         fprintf( stream, "\tt/u: %d : '%s'\n", ADDRITEM_TYPE(group), ADDRITEM_ID(group) );
742         fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(group) );
743         fprintf( stream, "\tgrp: '%s'\n", ADDRITEM_NAME(group) );
744         fprintf( stream, "\trem: '%s'\n", group->remarks );
745         fprintf( stream, "\t---\n" );
746         node = group->listEMail;
747         while( node ) {
748                 item = node->data;
749                 person = ( ItemPerson * ) ADDRITEM_PARENT(item);
750                 if( person ) {
751                         fprintf( stream, "\t\tpid : '%s'\n", ADDRITEM_ID(person) );
752                         fprintf( stream, "\t\tcomn: '%s'\n", ADDRITEM_NAME(person) );
753                 }
754                 else {
755                         fprintf( stream, "\t\tpid : ???\n" );
756                         fprintf( stream, "\t\tcomn: ???\n" );
757                 }
758                 addritem_print_item_email( item, stream );
759                 node = g_list_next( node );
760         }
761         fprintf( stream, "\t***\n" );
762 }
763
764 /*
765 * Create new address folder.
766 */
767 ItemFolder *addritem_create_item_folder( void ) {
768         ItemFolder *folder;
769         folder = g_new0( ItemFolder, 1 );
770         ADDRITEM_TYPE(folder) = ITEMTYPE_FOLDER;
771         ADDRITEM_ID(folder) = NULL;
772         ADDRITEM_NAME(folder) = NULL;
773         ADDRITEM_PARENT(folder) = NULL;
774         ADDRITEM_SUBTYPE(folder) = 0;
775         folder->remarks = NULL;
776         folder->isRoot = FALSE;
777         folder->listItems = NULL;
778         folder->listFolder = NULL;
779         folder->listPerson = NULL;
780         folder->listGroup = NULL;
781         folder->folderType = ADDRFOLDER_NONE;
782         folder->folderData = NULL;
783         return folder;
784 }
785
786 /*
787 * Copy address book folder.
788 * Enter:  item Folder to copy.
789 * Return: A copy of the folder. 
790 */
791 ItemFolder *addritem_copy_item_folder( ItemFolder *item ) {
792         ItemFolder *itemNew;
793
794         itemNew = g_new0( ItemFolder, 1 );
795         if( item ) {
796                 itemNew = addritem_create_item_folder();
797                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
798                 itemNew->folderType = item->folderType;
799         }
800         return itemNew;
801 }
802
803 /*
804 * Specify name to be used.
805 */
806 void addritem_folder_set_id( ItemFolder *folder, const gchar *value ) {
807         ADDRITEM_ID(folder) = mgu_replace_string( ADDRITEM_ID(folder), value );
808 }
809 void addritem_folder_set_name( ItemFolder *folder, const gchar *value ) {
810         ADDRITEM_NAME(folder) = mgu_replace_string( ADDRITEM_NAME(folder), value );
811 }
812 void addritem_folder_set_remarks( ItemFolder *folder, const gchar *value ) {
813         folder->remarks = mgu_replace_string( folder->remarks, value );
814 }
815
816 /*
817 * Free address folder. Note: this does not free up the lists of children
818 * (folders, groups and person). This should be done prior to calling this
819 * function.
820 */
821 void addritem_free_item_folder( ItemFolder *folder ) {
822         g_return_if_fail( folder != NULL );
823
824         /* Free internal stuff */
825         g_free( ADDRITEM_ID(folder) );
826         g_free( ADDRITEM_NAME(folder) );
827         g_free( folder->remarks );
828         mgu_clear_list( folder->listItems );
829         g_list_free( folder->listItems );
830
831         ADDRITEM_TYPE(folder) = ITEMTYPE_NONE;
832         ADDRITEM_ID(folder) = NULL;
833         ADDRITEM_NAME(folder) = NULL;
834         ADDRITEM_PARENT(folder) = NULL;
835         ADDRITEM_SUBTYPE(folder) = 0;
836         folder->isRoot = FALSE;
837         folder->remarks = NULL;
838         folder->listItems = NULL;
839         folder->listFolder = NULL;
840         folder->listGroup = NULL;
841         folder->listPerson = NULL;
842         folder->folderType = ADDRFOLDER_NONE;
843         folder->folderData = NULL;
844
845         g_free( folder );
846 }
847
848 /*
849 * Free up folders recursively. Note: this does not free up the lists of children
850 * (folders, groups and person). This should be done prior to calling this
851 * function.
852 */
853 void addritem_free_item_folder_recurse( ItemFolder *parent ) {
854         GList *node = parent->listFolder;
855
856         while( node ) {
857                 ItemFolder *folder = node->data;
858                 addritem_free_item_folder_recurse( folder );
859                 node = g_list_next( node );
860         }
861         g_list_free( parent->listPerson );
862         g_list_free( parent->listGroup );
863         g_list_free( parent->listFolder );
864         parent->listPerson = NULL;
865         parent->listGroup = NULL;
866         parent->listFolder = NULL;
867 }
868
869 /*
870 * Free up list of persons in specified folder.
871 */
872 void addritem_folder_free_person( ItemFolder *folder ) {
873         GList *node;
874
875         g_return_if_fail( folder != NULL );
876         
877         /* Free up folder of persons. */
878         node = folder->listPerson;
879         while( node ) {
880                 ItemPerson *person = node->data;
881                 addritem_free_item_person( person );
882                 person = NULL;
883                 node = g_list_next( node );
884         }
885 }
886
887 /*
888 * Add person into folder.
889 * return: TRUE if person added.
890 */
891 gboolean addritem_folder_add_person( ItemFolder *folder, ItemPerson *item ) {
892         g_return_val_if_fail( folder != NULL, FALSE );
893         g_return_val_if_fail( item != NULL, FALSE );
894
895         folder->listPerson = g_list_append( folder->listPerson, item );
896         ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
897         return TRUE;
898 }
899
900 /*
901 * Add folder into folder.
902 * return: TRUE if folder added.
903 */
904 gboolean addritem_folder_add_folder( ItemFolder *folder, ItemFolder *item ) {
905         g_return_val_if_fail( folder != NULL, FALSE );
906         g_return_val_if_fail( item != NULL, FALSE );
907
908         folder->listFolder = g_list_append( folder->listFolder, item );
909         ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
910         return TRUE;
911 }
912
913 /*
914 * Add group into folder.
915 * return: TRUE if folder added.
916 */
917 gboolean addritem_folder_add_group( ItemFolder *folder, ItemGroup *item ) {
918         g_return_val_if_fail( folder != NULL, FALSE );
919         g_return_val_if_fail( item != NULL, FALSE );
920
921         folder->listGroup = g_list_append( folder->listGroup, item );
922         ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
923         return TRUE;
924 }
925
926 /*
927 * Print address folder item.
928 */
929 void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) {
930         GList *node;
931         /* ItemPerson *person; */
932         ItemFolder *parent;
933
934         g_return_if_fail( folder != NULL );
935
936         fprintf( stream, "Folder:\n" );
937         fprintf( stream, "\tt/u: %d : '%s'\n", ADDRITEM_TYPE(folder), ADDRITEM_ID(folder) );
938         fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(folder) );
939         fprintf( stream, "\tnam: '%s'\n", ADDRITEM_NAME(folder) );
940         fprintf( stream, "\trem: '%s'\n", folder->remarks );
941         fprintf( stream, "\ttyp: %d\n", folder->folderType );
942         fprintf( stream, "\t---\n" );
943         parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
944         if( parent ) {
945                 fprintf( stream, "\tpar: %s : %s\n", ADDRITEM_ID(parent), ADDRITEM_NAME(parent) );
946         }
947         else {
948                 fprintf( stream, "\tpar: NULL\n" );
949         }
950         node = folder->listFolder;
951         while( node ) {
952                 AddrItemObject *aio = node->data;
953                 if( aio ) {
954                         if( aio->type == ITEMTYPE_FOLDER ) {
955                                 ItemFolder *item = ( ItemFolder * ) aio;
956                                 addritem_print_item_folder( item, stream );
957                         }
958                 }
959                 else {
960                         fprintf( stream, "\t\tpid : ???\n" );
961                 }
962
963                 node = g_list_next( node );
964         }
965
966         node = folder->listPerson;
967         while( node ) {
968                 AddrItemObject *aio = node->data;
969                 if( aio ) {
970                         if( aio->type == ITEMTYPE_PERSON ) {
971                                 ItemPerson *item = ( ItemPerson * ) aio;
972                                 addritem_print_item_person( item, stream );
973                         }
974                 }
975                 else {
976                         fprintf( stream, "\t\tpid : ???\n" );
977                 }
978
979                 node = g_list_next( node );
980         }
981
982         node = folder->listGroup;
983         while( node ) {
984                 AddrItemObject *aio = node->data;
985                 if( aio ) {
986                         if( aio->type == ITEMTYPE_GROUP ) {
987                                 ItemGroup *item = ( ItemGroup * ) aio;
988                                 addritem_print_item_group( item, stream );
989                         }
990                 }
991                 else {
992                         fprintf( stream, "\t\tpid : ???\n" );
993                 }
994                 node = g_list_next( node );
995         }
996         fprintf( stream, "\t###\n" );
997 }
998
999 /*
1000 * Print address item.
1001 */
1002 void addritem_print_item( AddrItemObject *aio, FILE *stream ) {
1003         g_return_if_fail( aio != NULL );
1004
1005         if( aio->type == ITEMTYPE_PERSON ) {
1006                 ItemPerson *item = ( ItemPerson * ) aio;
1007                 addritem_print_item_person( item, stream );
1008         }
1009         else if( aio->type == ITEMTYPE_EMAIL ) {
1010                 ItemEMail *item = ( ItemEMail * ) aio;
1011                 addritem_print_item_email( item, stream );
1012         }
1013         else if( aio->type == ITEMTYPE_GROUP ) {
1014                 ItemGroup *item = ( ItemGroup * ) aio;
1015                 addritem_print_item_group( item, stream );
1016         }
1017         else if( aio->type == ITEMTYPE_FOLDER ) {
1018                 ItemFolder *item = ( ItemFolder * ) aio;
1019                 addritem_print_item_folder( item, stream );
1020         }
1021 }
1022
1023 /*
1024 * Return link list of persons for specified folder. Note that the list contains
1025 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1026 * addritem_free_xxx() functions... this will destroy the addressbook data!
1027 * Return: List of items, or NULL if none.
1028 */
1029 GList *addritem_folder_get_person_list( ItemFolder *folder ) {
1030         GList *list = NULL;
1031         GList *node = NULL;
1032
1033         g_return_val_if_fail( folder != NULL, NULL );
1034
1035         node = folder->listPerson;
1036         while( node ) {
1037                 ItemPerson *person = node->data;
1038                 list = g_list_append( list, person );
1039                 node = g_list_next( node );
1040         }
1041         return list;
1042 }
1043
1044 /*
1045 * Return link list of groups for specified folder. Note that the list contains
1046 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1047 * addritem_free_xxx() functions... this will destroy the addressbook data!
1048 * Return: List of items, or NULL if none.
1049 */
1050 GList *addritem_folder_get_group_list( ItemFolder *folder ) {
1051         GList *list = NULL;
1052         GList *node = NULL;
1053
1054         g_return_val_if_fail( folder != NULL, NULL );
1055
1056         node = folder->listGroup;
1057         while( node ) {
1058                 ItemGroup *group = node->data;
1059                 list = g_list_append( list, group );
1060                 node = g_list_next( node );
1061         }
1062         return list;
1063 }
1064
1065 /*
1066 * Move person's email item.
1067 * param: person     Person.
1068 *        itemMove   Item to move.
1069 *        itemTarget Target item before which to move item.
1070 */
1071
1072 ItemEMail *addritem_move_email_before( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget ) {
1073         gint posT, posM;
1074
1075         g_return_val_if_fail( person != NULL, NULL );
1076
1077         if( itemTarget == NULL ) return NULL;
1078         if( itemMove == NULL ) return NULL;
1079         if( itemMove == itemTarget ) return itemMove;
1080
1081         posT = g_list_index( person->listEMail, itemTarget );
1082         if( posT < 0 ) return NULL;
1083         posM = g_list_index( person->listEMail, itemMove );
1084         if( posM < 0 ) return NULL;
1085         person->listEMail = g_list_remove( person->listEMail, itemMove );
1086         person->listEMail = g_list_insert( person->listEMail, itemMove, posT );
1087         return itemMove;
1088 }
1089
1090 /*
1091 * Move person's email item.
1092 * param: person     Person.
1093 *        itemMove   Item to move.
1094 *        itemTarget Target item after which to move item.
1095 */
1096 ItemEMail *addritem_move_email_after( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget ) {
1097         gint posT, posM;
1098
1099         g_return_val_if_fail( person != NULL, NULL );
1100
1101         if( itemTarget == NULL ) return NULL;
1102         if( itemMove == NULL ) return NULL;
1103         if( itemMove == itemTarget ) return itemMove;
1104
1105         posT = g_list_index( person->listEMail, itemTarget );
1106         if( posT < 0 ) return NULL;
1107         posM = g_list_index( person->listEMail, itemMove );
1108         if( posM < 0 ) return NULL;
1109         person->listEMail = g_list_remove( person->listEMail, itemMove );
1110         person->listEMail = g_list_insert( person->listEMail, itemMove, 1+posT );
1111         return itemMove;
1112 }
1113
1114 /**
1115  * Parse first and last names for person from common name.
1116  * Enter: person Person to process.
1117  */
1118 void addritem_parse_first_last( ItemPerson *person ) {
1119         gchar *name;
1120         gchar *fName, *lName;
1121         gchar *p;
1122         gint len, i;
1123
1124         g_return_if_fail( person != NULL );
1125
1126         name = ADDRITEM_NAME(person);
1127         if( name == NULL ) return;
1128
1129         fName = NULL;
1130         lName = NULL;
1131         p = strchr( name, ',' );
1132         if( p ) {
1133                 len = ( size_t ) ( p - name );
1134                 lName = g_strndup( name, len );
1135                 fName = g_strdup( p + 1 );
1136         }
1137         else {
1138                 /* Other way around */
1139                 i = strlen( name );
1140                 while( i >= 0 ) {
1141                         if( name[i] == ' ' ) {
1142                                 fName = g_strndup( name, i );
1143                                 lName = g_strdup( &name[i] );
1144                                 break;
1145                         }
1146                         i--;
1147                 }
1148                 if( fName == NULL ) {
1149                         fName = g_strdup( name );
1150                 }
1151         }
1152
1153         if( person->firstName ) {
1154                 g_free( person->firstName );
1155         }
1156         person->firstName = fName;
1157         if( person->firstName )
1158                 g_strstrip( person->firstName );
1159
1160         if( person->lastName ) {
1161                 g_free( person->lastName );
1162         }
1163         person->lastName = lName;
1164         if( person->lastName )
1165                 g_strstrip( person->lastName );
1166 }
1167
1168 /*
1169  * Build a path of all ancestor folders for specified folder.
1170  * Enter:  folder Folder.
1171  *         seq    Path sequence, FALSE top down, TRUE bottom up.
1172  * Return: List of folders from the top down.
1173  */
1174 GList *addritem_folder_path( const ItemFolder *folder, const gboolean seq ) {
1175         GList *list;
1176         AddrItemObject *item;
1177
1178         list = NULL;
1179         item = ( AddrItemObject * ) folder;
1180         if( seq ) {
1181                 while( item ) {
1182                         list = g_list_prepend( list, item );
1183                         item = ADDRITEM_PARENT( item );
1184                 }
1185         }
1186         else {
1187                 while( item ) {
1188                         list = g_list_append( list, item );
1189                         item = ADDRITEM_PARENT( item );
1190                 }
1191         }
1192         return list;
1193 }
1194
1195 /*
1196 * End of Source.
1197 */