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