Export address book to HTML.
[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 * Free linked list of item addresses.
231 */
232 void addritem_free_list_email( GList *list ) {
233         GList *node = list;
234         while( node ) {
235                 addritem_free_item_email( node->data );
236                 node->data = NULL;
237                 node = g_list_next( node );
238         }
239         g_list_free( list );
240 }
241
242 /*
243 * Free linked list of attributes.
244 */
245 void addritem_free_list_attribute( GList *list ) {
246         GList *node = list;
247         while( node ) {
248                 addritem_free_attribute( node->data );
249                 node->data = NULL;
250                 node = g_list_next( node );
251         }
252         g_list_free( list );
253 }
254
255 /*
256 * Free address person.
257 */
258 void addritem_free_item_person( ItemPerson *person ) {
259         g_return_if_fail( person != NULL );
260
261         /* Free internal stuff */
262         g_free( ADDRITEM_ID(person) );
263         g_free( ADDRITEM_NAME(person) );
264         g_free( person->firstName );
265         g_free( person->lastName );
266         g_free( person->nickName );
267         g_free( person->externalID );
268         addritem_free_list_email( person->listEMail );
269         addritem_free_list_attribute( person->listAttrib );
270
271         ADDRITEM_OBJECT(person)->type = ITEMTYPE_NONE;
272         ADDRITEM_ID(person) = NULL;
273         ADDRITEM_NAME(person) = NULL;
274         ADDRITEM_PARENT(person) = NULL;
275         ADDRITEM_SUBTYPE(person) = 0;
276         person->firstName = NULL;
277         person->lastName = NULL;
278         person->nickName = NULL;
279         person->externalID = NULL;
280         person->listEMail = NULL;
281         person->listAttrib = NULL;
282
283         g_free( person );
284 }
285
286 /*
287 * Print address item.
288 */
289 void addritem_print_item_email( ItemEMail *item, FILE *stream ) {
290         g_return_if_fail( item != NULL );
291         fprintf( stream, "\t\tt/id: %d : '%s'\n", ADDRITEM_TYPE(item), ADDRITEM_ID(item) );
292         fprintf( stream, "\t\tsubty: %d\n", ADDRITEM_SUBTYPE(item) );
293         fprintf( stream, "\t\talis: '%s'\n", ADDRITEM_NAME(item) );
294         fprintf( stream, "\t\taddr: '%s'\n", item->address );
295         fprintf( stream, "\t\trems: '%s'\n", item->remarks );
296         fprintf( stream, "\t\t---\n" );
297 }
298
299 /*
300 * Print user attribute.
301 */
302 void addritem_print_attribute( UserAttribute *item, FILE *stream ) {
303         g_return_if_fail( item != NULL );
304         fprintf( stream, "\t\tuid  : '%s'\n", item->uid );
305         fprintf( stream, "\t\tname : '%s'\n", item->name );
306         fprintf( stream, "\t\tvalue: '%s'\n", item->value );
307         fprintf( stream, "\t\t---\n" );
308 }
309
310 /*
311 * Print person item.
312 */
313 void addritem_print_item_person( ItemPerson *person, FILE *stream ) {
314         GList *node;
315         g_return_if_fail( person != NULL );
316         fprintf( stream, "Person:\n" );
317         fprintf( stream, "\tt/uid: %d : '%s'\n", ADDRITEM_TYPE(person), ADDRITEM_ID(person) );
318         fprintf( stream, "\tsubty: %d\n", ADDRITEM_SUBTYPE(person) );
319         fprintf( stream, "\tcommn: '%s'\n", ADDRITEM_NAME(person) );
320         fprintf( stream, "\tfirst: '%s'\n", person->firstName );
321         fprintf( stream, "\tlast : '%s'\n", person->lastName );
322         fprintf( stream, "\tnick : '%s'\n", person->nickName );
323         fprintf( stream, "\textID: '%s'\n", person->externalID );
324         fprintf( stream, "\teMail:\n" );
325         fprintf( stream, "\t---\n" );
326         node = person->listEMail;
327         while( node ) {
328                 addritem_print_item_email( node->data, stream );
329                 node = g_list_next( node );
330         }
331         fprintf( stream, "\tuAttr:\n" );
332         fprintf( stream, "\t---\n" );
333         node = person->listAttrib;
334         while( node ) {
335                 addritem_print_attribute( node->data, stream );
336                 node = g_list_next( node );
337         }
338         fprintf( stream, "\t===\n" );
339 }
340
341 /*
342 * Add EMail address to person.
343 * return: TRUE if item added.
344 */
345 gboolean addritem_person_add_email( ItemPerson *person, ItemEMail *email ) {
346         GList *node;
347
348         g_return_val_if_fail( person != NULL, FALSE );
349         g_return_val_if_fail( email != NULL, FALSE );
350
351         node = person->listEMail;
352         while( node ) {
353                 if( node->data == email ) return FALSE;
354                 node = g_list_next( node );
355         }
356         person->listEMail = g_list_append( person->listEMail, email );
357         ADDRITEM_PARENT(email) = ADDRITEM_OBJECT(person);
358         return TRUE;
359 }
360
361 /*
362 * Return email object with specified ID.
363 * param: person Person object.
364 *        eid    EMail ID.
365 * return: EMail object, or NULL if not found.
366 */
367 ItemEMail *addritem_person_get_email( ItemPerson *person, const gchar *eid ) {
368         ItemEMail *email = NULL;
369         GList *node;
370
371         g_return_val_if_fail( person != NULL, NULL );
372         if( eid == NULL || *eid == '\0' ) return NULL;
373
374         /* Look for email */
375         node = person->listEMail;
376         while( node ) {
377                 AddrItemObject *objE = node->data;
378                 gchar *ide = ADDRITEM_ID(objE);
379                 if( ide ) {
380                         if( strcmp( ide, eid ) == 0 ) {
381                                 email = ( ItemEMail * ) objE;
382                         }
383                 }
384                 node = g_list_next( node );
385         }
386         return email;
387 }
388
389 /*
390 * Remove email address for specified person.
391 * param: person Person object.
392 *        eid    EMail ID.
393 * return: EMail object, or NULL if not found. Note that object should still be freed.
394 */
395 ItemEMail *addritem_person_remove_email_id( ItemPerson *person, const gchar *eid ) {
396         ItemEMail *email = NULL;
397         GList *node;
398
399         g_return_val_if_fail( person != NULL, NULL );
400         if( eid == NULL || *eid == '\0' ) return NULL;
401
402         /* Look for email */
403         node = person->listEMail;
404         while( node ) {
405                 AddrItemObject *objE = node->data;
406                 gchar *ide = ADDRITEM_ID(objE);
407                 if( ide ) {
408                         if( strcmp( ide, eid ) == 0 ) {
409                                 email = ( ItemEMail * ) objE;
410                         }
411                 }
412                 node = g_list_next( node );
413         }
414
415         if( email ) {
416                 /* Remove email from person's address list */
417                 if( person->listEMail ) {
418                         person->listEMail = g_list_remove( person->listEMail, email );
419                 }
420                 /* Unlink reference to person. */
421                 ADDRITEM_PARENT(email) = NULL;
422         }
423         return email;
424 }
425
426 /*
427 * Remove email address for specified.
428 * param: person Person.
429 *        email  EMail to remove.
430 * return: EMail object, or NULL if not found. Note that object should still be freed.
431 */
432 ItemEMail *addritem_person_remove_email( ItemPerson *person, ItemEMail *email ) {
433         gboolean found = FALSE;
434         GList *node;
435
436         g_return_val_if_fail( person != NULL, NULL );
437         if( email == NULL ) return NULL;
438
439         /* Look for email */
440         node = person->listEMail;
441         while( node ) {
442                 if( node-> data == email ) {
443                         found = TRUE;
444                         break;
445                 }
446                 node = g_list_next( node );
447         }
448
449         if( found ) {
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                 return email;
457         }
458         return NULL;
459 }
460
461 /*
462 * Add user attribute to person.
463 * return: TRUE if item added.
464 */
465 void addritem_person_add_attribute( ItemPerson *person, UserAttribute *attrib ) {
466         g_return_if_fail( person != NULL );
467         person->listAttrib = g_list_append( person->listAttrib, attrib );
468 }
469
470 /*
471 * Return attribute with specified ID.
472 * param: person Person object.
473 *        aid    Attribute ID.
474 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
475 */
476 UserAttribute *addritem_person_get_attribute( ItemPerson *person, const gchar *aid ) {
477         UserAttribute *attrib = NULL;
478         GList *node;
479
480         g_return_val_if_fail( person != NULL, NULL );
481         if( aid == NULL || *aid == '\0' ) return NULL;
482
483         /* Look for attribute */
484         node = person->listAttrib;
485         while( node ) {
486                 UserAttribute *attr = node->data;
487                 gchar *ida = attr->uid;
488                 if( ida ) {
489                         if( strcmp( ida, aid ) == 0 ) {
490                                 attrib = attr;
491                         }
492                 }
493                 node = g_list_next( node );
494         }
495         return attrib;
496 }
497
498 /*
499 * Remove attribute from person.
500 * param: person Person object.
501 *        aid    Attribute ID.
502 * return: UserAttribute object, or NULL if not found. Note that object should still be freed.
503 */
504 UserAttribute *addritem_person_remove_attrib_id( ItemPerson *person, const gchar *aid ) {
505         UserAttribute *attrib = NULL;
506         GList *node;
507
508         g_return_val_if_fail( person != NULL, NULL );
509         if( aid == NULL || *aid == '\0' ) return NULL;
510
511         /* Look for attribute */
512         node = person->listAttrib;
513         while( node ) {
514                 UserAttribute *attr = node->data;
515                 gchar *ida = attr->uid;
516                 if( ida ) {
517                         if( strcmp( ida, aid ) == 0 ) {
518                                 attrib = attr;
519                         }
520                 }
521                 node = g_list_next( node );
522         }
523
524         /* Remove email from person's address list */
525         if( person->listAttrib ) {
526                 person->listAttrib = g_list_remove( person->listAttrib, attrib );
527         }
528         return attrib;
529 }
530
531 /*
532 * Remove attribute from person.
533 * param: person Person.
534 *        attrib Attribute to remove.
535 * return: UserAttribute object. Note that object should still be freed.
536 */
537 UserAttribute *addritem_person_remove_attribute( ItemPerson *person, UserAttribute *attrib ) {
538         gboolean found = FALSE;
539         GList *node;
540
541         g_return_val_if_fail( person != NULL, NULL );
542         if( attrib == NULL ) return NULL;
543
544         /* Look for attribute */
545         node = person->listAttrib;
546         while( node ) {
547                 if( node-> data == attrib ) {
548                         found = TRUE;
549                         break;
550                 }
551                 node = g_list_next( node );
552         }
553
554         if( found ) {
555                 /* Remove attribute */
556                 if( person->listAttrib ) {
557                         person->listAttrib = g_list_remove( person->listAttrib, attrib );
558                 }
559         }
560         return attrib;
561 }
562
563 /*
564 * Create new address book group.
565 */
566 ItemGroup *addritem_create_item_group( void ) {
567         ItemGroup *group;
568
569         group = g_new0( ItemGroup, 1 );
570         ADDRITEM_TYPE(group) = ITEMTYPE_GROUP;
571         ADDRITEM_ID(group) = NULL;
572         ADDRITEM_NAME(group) = NULL;
573         ADDRITEM_PARENT(group) = NULL;
574         ADDRITEM_SUBTYPE(group) = 0;
575         group->remarks = NULL;
576         group->listEMail = NULL;
577         return group;
578 }
579
580 /*
581 * Copy address book group.
582 * Enter:  item Group to copy.
583 * Return: A copy of the group. 
584 */
585 ItemGroup *addritem_copy_item_group( ItemGroup *item ) {
586         ItemGroup *itemNew;
587
588         itemNew = g_new0( ItemGroup, 1 );
589         if( item ) {
590                 itemNew = addritem_create_item_group();
591                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
592                 itemNew->remarks = g_strdup( item->remarks );
593         }
594         return itemNew;
595 }
596
597 /*
598 * Specify name to be used.
599 */
600 void addritem_group_set_id( ItemGroup *group, const gchar *value ) {
601         ADDRITEM_ID(group) = mgu_replace_string( ADDRITEM_ID(group), value );
602 }
603 void addritem_group_set_name( ItemGroup *group, const gchar *value ) {
604         ADDRITEM_NAME(group) = mgu_replace_string( ADDRITEM_NAME(group), value );
605 }
606 void addritem_group_set_remarks( ItemGroup *group, const gchar *value ) {
607         group->remarks = mgu_replace_string( group->remarks, value );
608 }
609
610 /*
611 * Free address group.
612 */
613 void addritem_free_item_group( ItemGroup *group ) {
614         g_return_if_fail( group != NULL );
615
616         /* Free internal stuff */
617         g_free( ADDRITEM_ID(group) );
618         g_free( ADDRITEM_NAME(group) );
619         g_free( group->remarks );
620         mgu_clear_list( group->listEMail );
621         g_list_free( group->listEMail );
622
623         ADDRITEM_TYPE(group) = ITEMTYPE_NONE;
624         ADDRITEM_ID(group) = NULL;
625         ADDRITEM_NAME(group) = NULL;
626         ADDRITEM_PARENT(group) = NULL;
627         ADDRITEM_SUBTYPE(group) = 0;
628         group->remarks = NULL;
629         group->listEMail = NULL;
630
631         g_free( group );
632 }
633
634 /*
635 * Add EMail address to group.
636 * return: TRUE if item added.
637 */
638 gboolean addritem_group_add_email( ItemGroup *group, ItemEMail *email ) {
639         GList *node;
640
641         g_return_val_if_fail( group != NULL, FALSE );
642         g_return_val_if_fail( email != NULL, FALSE );
643
644         node = group->listEMail;
645         while( node ) {
646                 if( node->data == email ) return FALSE;
647                 node = g_list_next( node );
648         }
649         group->listEMail = g_list_append( group->listEMail, email );
650         return TRUE;
651 }
652
653 /*
654 * Remove email address for specified group.
655 * param: group  Group from which to remove address.
656 *        email  EMail to remove
657 * return: EMail object, or NULL if email not found in group. Note that this object is
658 * referenced (linked) to a group and should *NOT* be freed. This object should only be
659 * freed after removing from a person.
660 */
661 ItemEMail *addritem_group_remove_email( ItemGroup *group, ItemEMail *email ) {
662         if( group && email ) {
663                 GList *node = group->listEMail;
664                 while( node ) {
665                         if( node->data == email ) {
666                                 group->listEMail = g_list_remove( group->listEMail, email );
667                                 return email;
668                         }
669                         node = g_list_next( node );
670                 }
671         }
672         return NULL;
673 }
674
675 /*
676 * Remove email address for specified group and ID.
677 * param: group  Group from which to remove address.
678 *        eid    EMail ID.
679 * return: EMail object, or NULL if email not found in group. Note that this object is
680 * referenced (linked) to a group and should *NOT* be freed. This object should only be
681 * freed after removing from a person.
682 */
683 ItemEMail *addritem_group_remove_email_id( ItemGroup *group, const gchar *eid ) {
684         if( group ) {
685                 GList *node = group->listEMail;
686                 while( node ) {
687                         ItemEMail *email = ( ItemEMail * ) node->data;
688                         if( strcmp( ADDRITEM_ID( email ), eid ) == 0 ) {
689                                 group->listEMail = g_list_remove( group->listEMail, email );
690                                 return email;
691                         }
692                         node = g_list_next( node );
693                 }
694         }
695         return NULL;
696 }
697
698 /*
699 * Print address group item.
700 */
701 void addritem_print_item_group( ItemGroup *group, FILE *stream ) {
702         GList *node;
703         ItemPerson *person;
704         ItemEMail *item;
705         g_return_if_fail( group != NULL );
706         fprintf( stream, "Group:\n" );
707         fprintf( stream, "\tt/u: %d : '%s'\n", ADDRITEM_TYPE(group), ADDRITEM_ID(group) );
708         fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(group) );
709         fprintf( stream, "\tgrp: '%s'\n", ADDRITEM_NAME(group) );
710         fprintf( stream, "\trem: '%s'\n", group->remarks );
711         fprintf( stream, "\t---\n" );
712         node = group->listEMail;
713         while( node ) {
714                 item = node->data;
715                 person = ( ItemPerson * ) ADDRITEM_PARENT(item);
716                 if( person ) {
717                         fprintf( stream, "\t\tpid : '%s'\n", ADDRITEM_ID(person) );
718                         fprintf( stream, "\t\tcomn: '%s'\n", ADDRITEM_NAME(person) );
719                 }
720                 else {
721                         fprintf( stream, "\t\tpid : ???\n" );
722                         fprintf( stream, "\t\tcomn: ???\n" );
723                 }
724                 addritem_print_item_email( item, stream );
725                 node = g_list_next( node );
726         }
727         fprintf( stream, "\t***\n" );
728 }
729
730 /*
731 * Create new address folder.
732 */
733 ItemFolder *addritem_create_item_folder( void ) {
734         ItemFolder *folder;
735         folder = g_new0( ItemFolder, 1 );
736         ADDRITEM_TYPE(folder) = ITEMTYPE_FOLDER;
737         ADDRITEM_ID(folder) = NULL;
738         ADDRITEM_NAME(folder) = NULL;
739         ADDRITEM_PARENT(folder) = NULL;
740         ADDRITEM_SUBTYPE(folder) = 0;
741         folder->remarks = NULL;
742         folder->isRoot = FALSE;
743         folder->listItems = NULL;
744         folder->listFolder = NULL;
745         folder->listPerson = NULL;
746         folder->listGroup = NULL;
747         return folder;
748 }
749
750 /*
751 * Copy address book folder.
752 * Enter:  item Folder to copy.
753 * Return: A copy of the folder. 
754 */
755 ItemFolder *addritem_copy_item_folder( ItemFolder *item ) {
756         ItemFolder *itemNew;
757
758         itemNew = g_new0( ItemFolder, 1 );
759         if( item ) {
760                 itemNew = addritem_create_item_folder();
761                 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
762         }
763         return itemNew;
764 }
765
766 /*
767 * Specify name to be used.
768 */
769 void addritem_folder_set_id( ItemFolder *folder, const gchar *value ) {
770         ADDRITEM_ID(folder) = mgu_replace_string( ADDRITEM_ID(folder), value );
771 }
772 void addritem_folder_set_name( ItemFolder *folder, const gchar *value ) {
773         ADDRITEM_NAME(folder) = mgu_replace_string( ADDRITEM_NAME(folder), value );
774 }
775 void addritem_folder_set_remarks( ItemFolder *folder, const gchar *value ) {
776         folder->remarks = mgu_replace_string( folder->remarks, value );
777 }
778
779 /*
780 * Free address folder. Note: this does not free up the lists of children
781 * (folders, groups and person). This should be done prior to calling this
782 * function.
783 */
784 void addritem_free_item_folder( ItemFolder *folder ) {
785         g_return_if_fail( folder != NULL );
786
787         /* Free internal stuff */
788         g_free( ADDRITEM_ID(folder) );
789         g_free( ADDRITEM_NAME(folder) );
790         g_free( folder->remarks );
791         mgu_clear_list( folder->listItems );
792         g_list_free( folder->listItems );
793
794         ADDRITEM_TYPE(folder) = ITEMTYPE_NONE;
795         ADDRITEM_ID(folder) = NULL;
796         ADDRITEM_NAME(folder) = NULL;
797         ADDRITEM_PARENT(folder) = NULL;
798         ADDRITEM_SUBTYPE(folder) = 0;
799         folder->isRoot = FALSE;
800         folder->remarks = NULL;
801         folder->listItems = NULL;
802         folder->listFolder = NULL;
803         folder->listGroup = NULL;
804         folder->listPerson = NULL;
805
806         g_free( folder );
807 }
808
809 /*
810 * Free up folders recursively. Note: this does not free up the lists of children
811 * (folders, groups and person). This should be done prior to calling this
812 * function.
813 */
814 void addritem_free_item_folder_recurse( ItemFolder *parent ) {
815         GList *node = parent->listFolder;
816
817         while( node ) {
818                 ItemFolder *folder = node->data;
819                 addritem_free_item_folder_recurse( folder );
820                 node = g_list_next( node );
821         }
822         g_list_free( parent->listPerson );
823         g_list_free( parent->listGroup );
824         g_list_free( parent->listFolder );
825         parent->listPerson = NULL;
826         parent->listGroup = NULL;
827         parent->listFolder = NULL;
828 }
829
830 /*
831 * Free up list of person in specified folder.
832 */
833 void addritem_folder_free_person( ItemFolder *folder ) {
834         GList *node;
835
836         g_return_if_fail( folder != NULL );
837         
838         /* Free up folder of persons. */
839         node = folder->listPerson;
840         while( node ) {
841                 ItemPerson *person = node->data;
842                 addritem_free_item_person( person );
843                 person = NULL;
844                 node = g_list_next( node );
845         }
846 }
847
848 /*
849 * Add person into folder.
850 * return: TRUE if person added.
851 */
852 gboolean addritem_folder_add_person( ItemFolder *folder, ItemPerson *item ) {
853         g_return_val_if_fail( folder != NULL, FALSE );
854         g_return_val_if_fail( item != NULL, FALSE );
855
856         folder->listPerson = g_list_append( folder->listPerson, item );
857         ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
858         return TRUE;
859 }
860
861 /*
862 * Add folder into folder.
863 * return: TRUE if folder added.
864 */
865 gboolean addritem_folder_add_folder( ItemFolder *folder, ItemFolder *item ) {
866         g_return_val_if_fail( folder != NULL, FALSE );
867         g_return_val_if_fail( item != NULL, FALSE );
868
869         folder->listFolder = g_list_append( folder->listFolder, item );
870         ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
871         return TRUE;
872 }
873
874 /*
875 * Add group into folder.
876 * return: TRUE if folder added.
877 */
878 gboolean addritem_folder_add_group( ItemFolder *folder, ItemGroup *item ) {
879         g_return_val_if_fail( folder != NULL, FALSE );
880         g_return_val_if_fail( item != NULL, FALSE );
881
882         folder->listGroup = g_list_append( folder->listGroup, item );
883         ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
884         return TRUE;
885 }
886
887 /*
888 * Print address folder item.
889 */
890 void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) {
891         GList *node;
892         /* ItemPerson *person; */
893         ItemFolder *parent;
894
895         g_return_if_fail( folder != NULL );
896
897         fprintf( stream, "Folder:\n" );
898         fprintf( stream, "\tt/u: %d : '%s'\n", ADDRITEM_TYPE(folder), ADDRITEM_ID(folder) );
899         fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(folder) );
900         fprintf( stream, "\tnam: '%s'\n", ADDRITEM_NAME(folder) );
901         fprintf( stream, "\trem: '%s'\n", folder->remarks );
902         fprintf( stream, "\t---\n" );
903         parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
904         if( parent ) {
905                 fprintf( stream, "\tpar: %s : %s\n", ADDRITEM_ID(parent), ADDRITEM_NAME(parent) );
906         }
907         else {
908                 fprintf( stream, "\tpar: NULL\n" );
909         }
910         node = folder->listFolder;
911         while( node ) {
912                 AddrItemObject *aio = node->data;
913                 if( aio ) {
914                         if( aio->type == ITEMTYPE_FOLDER ) {
915                                 ItemFolder *item = ( ItemFolder * ) aio;
916                                 addritem_print_item_folder( item, stream );
917                         }
918                 }
919                 else {
920                         fprintf( stream, "\t\tpid : ???\n" );
921                 }
922
923                 node = g_list_next( node );
924         }
925
926         node = folder->listPerson;
927         while( node ) {
928                 AddrItemObject *aio = node->data;
929                 if( aio ) {
930                         if( aio->type == ITEMTYPE_PERSON ) {
931                                 ItemPerson *item = ( ItemPerson * ) aio;
932                                 addritem_print_item_person( item, stream );
933                         }
934                 }
935                 else {
936                         fprintf( stream, "\t\tpid : ???\n" );
937                 }
938
939                 node = g_list_next( node );
940         }
941
942         node = folder->listGroup;
943         while( node ) {
944                 AddrItemObject *aio = node->data;
945                 if( aio ) {
946                         if( aio->type == ITEMTYPE_GROUP ) {
947                                 ItemGroup *item = ( ItemGroup * ) aio;
948                                 addritem_print_item_group( item, stream );
949                         }
950                 }
951                 else {
952                         fprintf( stream, "\t\tpid : ???\n" );
953                 }
954                 node = g_list_next( node );
955         }
956         fprintf( stream, "\t###\n" );
957 }
958
959 /*
960 * Print address item.
961 */
962 void addritem_print_item( AddrItemObject *aio, FILE *stream ) {
963         g_return_if_fail( aio != NULL );
964
965         if( aio->type == ITEMTYPE_PERSON ) {
966                 ItemPerson *item = ( ItemPerson * ) aio;
967                 addritem_print_item_person( item, stream );
968         }
969         else if( aio->type == ITEMTYPE_EMAIL ) {
970                 ItemEMail *item = ( ItemEMail * ) aio;
971                 addritem_print_item_email( item, stream );
972         }
973         else if( aio->type == ITEMTYPE_GROUP ) {
974                 ItemGroup *item = ( ItemGroup * ) aio;
975                 addritem_print_item_group( item, stream );
976         }
977         else if( aio->type == ITEMTYPE_FOLDER ) {
978                 ItemFolder *item = ( ItemFolder * ) aio;
979                 addritem_print_item_folder( item, stream );
980         }
981 }
982
983 /*
984 * Return link list of persons for specified folder. Note that the list contains
985 * references to items and should be g_free() when done. Do *NOT* attempt to use the
986 * addritem_free_xxx() functions... this will destroy the addressbook data!
987 * Return: List of items, or NULL if none.
988 */
989 GList *addritem_folder_get_person_list( ItemFolder *folder ) {
990         GList *list = NULL;
991         GList *node = NULL;
992
993         g_return_val_if_fail( folder != NULL, NULL );
994
995         node = folder->listPerson;
996         while( node ) {
997                 ItemPerson *person = node->data;
998                 list = g_list_append( list, person );
999                 node = g_list_next( node );
1000         }
1001         return list;
1002 }
1003
1004 /*
1005 * Return link list of groups for specified folder. Note that the list contains
1006 * references to items and should be g_free() when done. Do *NOT* attempt to use the
1007 * addritem_free_xxx() functions... this will destroy the addressbook data!
1008 * Return: List of items, or NULL if none.
1009 */
1010 GList *addritem_folder_get_group_list( ItemFolder *folder ) {
1011         GList *list = NULL;
1012         GList *node = NULL;
1013
1014         g_return_val_if_fail( folder != NULL, NULL );
1015
1016         node = folder->listGroup;
1017         while( node ) {
1018                 ItemGroup *group = node->data;
1019                 list = g_list_append( list, group );
1020                 node = g_list_next( node );
1021         }
1022         return list;
1023 }
1024
1025 /*
1026 * Move person's email item.
1027 * param: person     Person.
1028 *        itemMove   Item to move.
1029 *        itemTarget Target item before which to move item.
1030 */
1031
1032 ItemEMail *addritem_move_email_before( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget ) {
1033         gint posT, posM;
1034
1035         g_return_val_if_fail( person != NULL, NULL );
1036
1037         if( itemTarget == NULL ) return NULL;
1038         if( itemMove == NULL ) return NULL;
1039         if( itemMove == itemTarget ) return itemMove;
1040
1041         posT = g_list_index( person->listEMail, itemTarget );
1042         if( posT < 0 ) return NULL;
1043         posM = g_list_index( person->listEMail, itemMove );
1044         if( posM < 0 ) return NULL;
1045         person->listEMail = g_list_remove( person->listEMail, itemMove );
1046         person->listEMail = g_list_insert( person->listEMail, itemMove, posT );
1047         return itemMove;
1048 }
1049
1050 /*
1051 * Move person's email item.
1052 * param: person     Person.
1053 *        itemMove   Item to move.
1054 *        itemTarget Target item after which to move item.
1055 */
1056 ItemEMail *addritem_move_email_after( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget ) {
1057         gint posT, posM;
1058
1059         g_return_val_if_fail( person != NULL, NULL );
1060
1061         if( itemTarget == NULL ) return NULL;
1062         if( itemMove == NULL ) return NULL;
1063         if( itemMove == itemTarget ) return itemMove;
1064
1065         posT = g_list_index( person->listEMail, itemTarget );
1066         if( posT < 0 ) return NULL;
1067         posM = g_list_index( person->listEMail, itemMove );
1068         if( posM < 0 ) return NULL;
1069         person->listEMail = g_list_remove( person->listEMail, itemMove );
1070         person->listEMail = g_list_insert( person->listEMail, itemMove, 1+posT );
1071         return itemMove;
1072 }
1073
1074 /**
1075  * Parse first and last names for person from common name.
1076  * Enter: person Person to process.
1077  */
1078 void addritem_parse_first_last( ItemPerson *person ) {
1079         gchar *name;
1080         gchar *fName, *lName;
1081         gchar *p;
1082         gint len, i;
1083
1084         g_return_if_fail( person != NULL );
1085
1086         name = ADDRITEM_NAME(person);
1087         if( name == NULL ) return;
1088
1089         fName = NULL;
1090         lName = NULL;
1091         p = strchr( name, ',' );
1092         if( p ) {
1093                 len = ( size_t ) ( p - name );
1094                 lName = g_strndup( name, len );
1095                 fName = g_strdup( p + 1 );
1096         }
1097         else {
1098                 /* Other way around */
1099                 i = strlen( name );
1100                 while( i >= 0 ) {
1101                         if( name[i] == ' ' ) {
1102                                 fName = g_strndup( name, i );
1103                                 lName = g_strdup( &name[i] );
1104                                 break;
1105                         }
1106                         i--;
1107                 }
1108                 if( fName == NULL ) {
1109                         fName = g_strdup( name );
1110                 }
1111         }
1112
1113         if( person->firstName ) {
1114                 g_free( person->firstName );
1115         }
1116         person->firstName = fName;
1117         if( person->firstName )
1118                 g_strstrip( person->firstName );
1119
1120         if( person->lastName ) {
1121                 g_free( person->lastName );
1122         }
1123         person->lastName = lName;
1124         if( person->lastName )
1125                 g_strstrip( person->lastName );
1126 }
1127
1128 /*
1129  * Build a path of all ancestor folders for specified folder.
1130  * Enter:  folder Folder.
1131  *         seq    Path sequence, FALSE top down, TRUE bottom up.
1132  * Return: List of folders from the top down.
1133  */
1134 GList *addritem_folder_path( const ItemFolder *folder, const gboolean seq ) {
1135         GList *list;
1136         AddrItemObject *item;
1137
1138         list = NULL;
1139         item = ( AddrItemObject * ) folder;
1140         if( seq ) {
1141                 while( item ) {
1142                         list = g_list_prepend( list, item );
1143                         item = ADDRITEM_PARENT( item );
1144                 }
1145         }
1146         else {
1147                 while( item ) {
1148                         list = g_list_append( list, item );
1149                         item = ADDRITEM_PARENT( item );
1150                 }
1151         }
1152         return list;
1153 }
1154
1155 /*
1156 * End of Source.
1157 */