2007-01-20 [colin] 2.7.1cvs42
[claws.git] / src / addritem.c
index 84e92e7bfff0ed4b2bd7df059e73984fd19ff0b4..d71b281b5791b7782630da84984fa4444f136de8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001-2002 Match Grun
+ * Copyright (C) 2001-2007 Match Grun and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 /*
 #include <stdio.h>
 #include <string.h>
 
+#include "utils.h"
 #include "addritem.h"
 #include "mgutils.h"
+#include "codeconv.h"
 
-/*
-* Create new email address item.
-*/
+/**
+ * Create new email address item.
+ * \return Initialized email item.
+ */
 ItemEMail *addritem_create_item_email( void ) {
        ItemEMail *item;
        item = g_new0( ItemEMail, 1 );
@@ -44,10 +47,11 @@ ItemEMail *addritem_create_item_email( void ) {
        return item;
 }
 
-/*
-* Create a shallow copy of specified email address item.
-* Enter: item E-Mail to copy.
-*/
+/**
+ * Create a shallow copy of specified email address item.
+ * \param  item E-Mail to copy.
+ * \return Copy of email, or <i>NULL</i> if null argument supplied.
+ */
 ItemEMail *addritem_copy_item_email( ItemEMail *item ) {
        ItemEMail *itemNew = NULL;
        if( item ) {
@@ -59,10 +63,11 @@ ItemEMail *addritem_copy_item_email( ItemEMail *item ) {
        return itemNew;
 }
 
-/*
-* Create a full copy of specified email address item.
-* Enter: item E-Mail to copy.
-*/
+/**
+ * Create a full copy (deep copy) of specified email address item.
+ * \param  item E-Mail to copy.
+ * \return Copy of email.
+ */
 ItemEMail *addritem_copyfull_item_email( ItemEMail *item ) {
        ItemEMail *itemNew = NULL;
        if( item ) {
@@ -76,22 +81,37 @@ ItemEMail *addritem_copyfull_item_email( ItemEMail *item ) {
        return itemNew;
 }
 
-void addritem_email_set_id( ItemEMail *email, const gchar *value ) {
-       ADDRITEM_ID(email) = mgu_replace_string( ADDRITEM_ID(email), value );
-}
+/**
+ * Specify alias for email.
+ * \param email E-Mail item.
+ * \param value Alias.
+ */
 void addritem_email_set_alias( ItemEMail *email, const gchar *value ) {
        ADDRITEM_NAME(email) = mgu_replace_string( ADDRITEM_NAME(email), value );
 }
+
+/**
+ * Specify address for email.
+ * \param email E-Mail item.
+ * \param value Address.
+ */
 void addritem_email_set_address( ItemEMail *email, const gchar *value ) {
        email->address = mgu_replace_string( email->address, value );
 }
+
+/**
+ * Specify remarks for email.
+ * \param email E-Mail item.
+ * \param value Remarks.
+ */
 void addritem_email_set_remarks( ItemEMail *email, const gchar *value ) {
        email->remarks = mgu_replace_string( email->remarks, value );
 }
 
-/*
-* Free address item email.
-*/
+/**
+ * Free address item email object.
+ * \param item E-Mail item to free.
+ */
 void addritem_free_item_email( ItemEMail *item ) {
        g_return_if_fail( item != NULL );
 
@@ -111,9 +131,10 @@ void addritem_free_item_email( ItemEMail *item ) {
        g_free( item );
 }
 
-/*
-* Create new attribute.
-*/
+/**
+ * Create new attribute object.
+ * \return Initialized attribute object.
+ */
 UserAttribute *addritem_create_attribute( void ) {
        UserAttribute *item;
        item = g_new0( UserAttribute, 1 );
@@ -123,9 +144,11 @@ UserAttribute *addritem_create_attribute( void ) {
        return item;
 }
 
-/*
-* Create copy of specified attribute.
-*/
+/**
+ * Create copy (deep copy) of specified attribute.
+ * \param  item Attribute to copy.
+ * \return Copy of attribute, or <i>NULL</i> if null argument supplied.
+ */
 UserAttribute *addritem_copy_attribute( UserAttribute *item ) {
        UserAttribute *itemNew = NULL;
        if( item ) {
@@ -137,22 +160,40 @@ UserAttribute *addritem_copy_attribute( UserAttribute *item ) {
        return itemNew;
 }
 
+/**
+ * Specify ID for attribute.
+ * \param item Attribute object.
+ * \param value ID.
+ */
 void addritem_attrib_set_id( UserAttribute *item, const gchar *value ) {
        g_return_if_fail( item != NULL );
        item->uid = mgu_replace_string( item->uid, value );
 }
+
+/**
+ * Specify name for attribute.
+ * \param item Attribute object.
+ * \param value Name.
+ */
 void addritem_attrib_set_name( UserAttribute *item, const gchar *value ) {
        g_return_if_fail( item != NULL );
        item->name = mgu_replace_string( item->name, value );
 }
+
+/**
+ * Specify value for attribute.
+ * \param item Attribute object.
+ * \param value Value.
+ */
 void addritem_attrib_set_value( UserAttribute *item, const gchar *value ) {
        g_return_if_fail( item != NULL );
        item->value = mgu_replace_string( item->value, value );
 }
 
-/*
-* Free user attribute.
-*/
+/**
+ * Free user attribute.
+ * \param item Attribute object to free.
+ */
 void addritem_free_attribute( UserAttribute *item ) {
        g_return_if_fail( item != NULL );
        g_free( item->uid );
@@ -164,9 +205,10 @@ void addritem_free_attribute( UserAttribute *item ) {
        g_free( item );
 }
 
-/*
-* Create new address book person.
-*/
+/**
+ * Create new address book person.
+ * \return Initialized person object.
+ */
 ItemPerson *addritem_create_item_person( void ) {
        ItemPerson *person;
        person = g_new0( ItemPerson, 1 );
@@ -185,10 +227,11 @@ ItemPerson *addritem_create_item_person( void ) {
        return person;
 }
 
-/*
-* Create a shallow copy of address book person.
-* Enter: item Person to copy.
-*/
+/**
+ * Create a shallow copy of address book person object.
+ * \param  item Person to copy.
+ * \return Copy of person, or <i>NULL</i> if null argument supplied.
+ */
 ItemPerson *addritem_copy_item_person( ItemPerson *item ) {
        ItemPerson *itemNew;
 
@@ -204,44 +247,150 @@ ItemPerson *addritem_copy_item_person( ItemPerson *item ) {
        return itemNew;
 }
 
-void addritem_person_set_id( ItemPerson *person, const gchar *value ) {
-       ADDRITEM_ID(person) = mgu_replace_string( ADDRITEM_ID(person), value );
-}
+/**
+ * Specify first name for person object.
+ * \param person Person object.
+ * \param value Name.
+ */
 void addritem_person_set_first_name( ItemPerson *person, const gchar *value ) {
-       person->firstName = mgu_replace_string( person->firstName, value );
+       if (!value || g_utf8_validate(value, -1, NULL))
+               person->firstName = mgu_replace_string( person->firstName, value );
+       else {
+               gchar *out = conv_codeset_strdup(value, 
+                               conv_get_locale_charset_str_no_utf8(),
+                               CS_INTERNAL);
+               if (out)
+                       person->firstName = mgu_replace_string( person->firstName, out );
+               g_free(out);
+       }
 }
+
+/**
+ * Specify last name for person object.
+ * \param person Person object.
+ * \param value name.
+ */
 void addritem_person_set_last_name( ItemPerson *person, const gchar *value ) {
-       person->lastName = mgu_replace_string( person->lastName, value );
+       if (!value || g_utf8_validate(value, -1, NULL))
+               person->lastName = mgu_replace_string( person->lastName, value );
+       else {
+               gchar *out = conv_codeset_strdup(value, 
+                               conv_get_locale_charset_str_no_utf8(),
+                               CS_INTERNAL);
+               if (out)
+                       person->lastName = mgu_replace_string( person->lastName, out );
+               g_free(out);
+       }
 }
+
+/**
+ * Specify nick name for person object.
+ * \param person Person object.
+ * \param value name.
+ */
 void addritem_person_set_nick_name( ItemPerson *person, const gchar *value ) {
-       person->nickName = mgu_replace_string( person->nickName, value );
+       if (!value || g_utf8_validate(value, -1, NULL))
+               person->nickName = mgu_replace_string( person->nickName, value );
+       else {
+               gchar *out = conv_codeset_strdup(value, 
+                               conv_get_locale_charset_str_no_utf8(),
+                               CS_INTERNAL);
+               if (out)
+                       person->nickName = mgu_replace_string( person->nickName, out );
+               g_free(out);
+       }
 }
+
+/**
+ * Specify common name for person object.
+ * \param person Person object.
+ * \param value name.
+ */
 void addritem_person_set_common_name( ItemPerson *person, const gchar *value ) {
-       ADDRITEM_NAME(person) = mgu_replace_string( ADDRITEM_NAME(person), value );
+       if (!value || g_utf8_validate(value, -1, NULL))
+               ADDRITEM_NAME(person) = mgu_replace_string( ADDRITEM_NAME(person), value );
+       else {
+               gchar *out = conv_codeset_strdup(value, 
+                               conv_get_locale_charset_str_no_utf8(),
+                               CS_INTERNAL);
+               if (out)
+                       ADDRITEM_NAME(person) = mgu_replace_string( ADDRITEM_NAME(person), out );
+               g_free(out);
+       }
 }
+
+/**
+ * Specify external ID for person object.
+ * \param person Person object.
+ * \param value ID.
+ */
 void addritem_person_set_external_id( ItemPerson *person, const gchar *value ) {
        person->externalID = mgu_replace_string( person->externalID, value );
 }
+
+/**
+ * Specify value of open indicator for person object. This is typically used to
+ * simplify open/close folders in the address book GUI.
+ * \param person Person object.
+ * \param value  Value for indicator. Set to <i>TRUE</i> if opened.
+ */
 void addritem_person_set_opened( ItemPerson *person, const gboolean value ) {
        person->isOpened = value;
 }
 
-/*
-* Free linked list of item addresses.
-*/
+/**
+ * Test whether person's data is empty.
+ * \param  person Person to test.
+ * \return <i>TRUE</i> if empty.
+ */
+gboolean addritem_person_empty( ItemPerson *person ) {
+       gchar *t;
+
+       if( person == NULL ) return FALSE;
+
+       t = ADDRITEM_NAME(person);
+       if( t != NULL && strlen( t ) > 0 ) return FALSE;
+
+       t = person->firstName;
+       if( t != NULL && strlen( t ) > 0 ) return FALSE;
+
+       t = person->lastName;
+       if( t != NULL && strlen( t ) > 0 ) return FALSE;
+
+       t = person->nickName;
+       if( t != NULL && strlen( t ) > 0 ) return FALSE;
+
+       if( person->listEMail  != NULL ) return FALSE;
+       if( person->listAttrib != NULL ) return FALSE;
+
+       return TRUE;
+}
+
+/**
+ * Free linked list of item addresses; both addresses and the list are freed.
+ * It is assumed that addresses are *NOT* contained within some other
+ * container.
+ * \param list List of addresses to be freed.
+ */
 void addritem_free_list_email( GList *list ) {
        GList *node = list;
        while( node ) {
-               addritem_free_item_email( node->data );
+               ItemEMail *email = node->data;
+
+               addritem_free_item_email( email );
                node->data = NULL;
                node = g_list_next( node );
        }
        g_list_free( list );
+       list = NULL;
 }
 
-/*
-* Free linked list of attributes.
-*/
+/**
+ * Free linked list of attributes; both attributes and the list are freed.
+ * It is assumed that attributes are *NOT* contained within some other
+ * container.
+ * \param list List of attributes to be freed.
+ */
 void addritem_free_list_attribute( GList *list ) {
        GList *node = list;
        while( node ) {
@@ -252,9 +401,10 @@ void addritem_free_list_attribute( GList *list ) {
        g_list_free( list );
 }
 
-/*
-* Free address person.
-*/
+/**
+ * Free address person object.
+ * \param person Person object to free.
+ */
 void addritem_free_item_person( ItemPerson *person ) {
        g_return_if_fail( person != NULL );
 
@@ -265,7 +415,7 @@ void addritem_free_item_person( ItemPerson *person ) {
        g_free( person->lastName );
        g_free( person->nickName );
        g_free( person->externalID );
-       addritem_free_list_email( person->listEMail );
+       g_list_free( person->listEMail );
        addritem_free_list_attribute( person->listAttrib );
 
        ADDRITEM_OBJECT(person)->type = ITEMTYPE_NONE;
@@ -283,9 +433,11 @@ void addritem_free_item_person( ItemPerson *person ) {
        g_free( person );
 }
 
-/*
-* Print address item.
-*/
+/**
+ * Print E-Mail address object for debug.
+ * \param item   Item to print.
+ * \param stream Output stream.
+ */
 void addritem_print_item_email( ItemEMail *item, FILE *stream ) {
        g_return_if_fail( item != NULL );
        fprintf( stream, "\t\tt/id: %d : '%s'\n", ADDRITEM_TYPE(item), ADDRITEM_ID(item) );
@@ -296,10 +448,12 @@ void addritem_print_item_email( ItemEMail *item, FILE *stream ) {
        fprintf( stream, "\t\t---\n" );
 }
 
-/*
-* Print user attribute.
-*/
-void addritem_print_attribute( UserAttribute *item, FILE *stream ) {
+/**
+ * Print user attribute object for debug.
+ * \param item   Attribute to print.
+ * \param stream Output stream.
+ */
+static void addritem_print_attribute( UserAttribute *item, FILE *stream ) {
        g_return_if_fail( item != NULL );
        fprintf( stream, "\t\tuid  : '%s'\n", item->uid );
        fprintf( stream, "\t\tname : '%s'\n", item->name );
@@ -307,9 +461,11 @@ void addritem_print_attribute( UserAttribute *item, FILE *stream ) {
        fprintf( stream, "\t\t---\n" );
 }
 
-/*
-* Print person item.
-*/
+/**
+ * Print person item for debug.
+ * \param person Person to print.
+ * \param stream Output stream.
+ */
 void addritem_print_item_person( ItemPerson *person, FILE *stream ) {
        GList *node;
        g_return_if_fail( person != NULL );
@@ -338,10 +494,12 @@ void addritem_print_item_person( ItemPerson *person, FILE *stream ) {
        fprintf( stream, "\t===\n" );
 }
 
-/*
-* Add EMail address to person.
-* return: TRUE if item added.
-*/
+/**
+ * Add E-Mail address object to person.
+ * \param  person Person.
+ * \param  email  E-Mail object to add.
+ * \return <i>TRUE</i> if E-Mail added.
+ */
 gboolean addritem_person_add_email( ItemPerson *person, ItemEMail *email ) {
        GList *node;
 
@@ -358,77 +516,13 @@ gboolean addritem_person_add_email( ItemPerson *person, ItemEMail *email ) {
        return TRUE;
 }
 
-/*
-* Return email object with specified ID.
-* param: person Person object.
-*        eid   EMail ID.
-* return: EMail object, or NULL if not found.
-*/
-ItemEMail *addritem_person_get_email( ItemPerson *person, const gchar *eid ) {
-       ItemEMail *email = NULL;
-       GList *node;
-
-       g_return_val_if_fail( person != NULL, NULL );
-       if( eid == NULL || *eid == '\0' ) return NULL;
-
-       /* Look for email */
-       node = person->listEMail;
-       while( node ) {
-               AddrItemObject *objE = node->data;
-               gchar *ide = ADDRITEM_ID(objE);
-               if( ide ) {
-                       if( strcmp( ide, eid ) == 0 ) {
-                               email = ( ItemEMail * ) objE;
-                       }
-               }
-               node = g_list_next( node );
-       }
-       return email;
-}
-
-/*
-* Remove email address for specified person.
-* param: person Person object.
-*        eid   EMail ID.
-* return: EMail object, or NULL if not found. Note that object should still be freed.
-*/
-ItemEMail *addritem_person_remove_email_id( ItemPerson *person, const gchar *eid ) {
-       ItemEMail *email = NULL;
-       GList *node;
-
-       g_return_val_if_fail( person != NULL, NULL );
-       if( eid == NULL || *eid == '\0' ) return NULL;
-
-       /* Look for email */
-       node = person->listEMail;
-       while( node ) {
-               AddrItemObject *objE = node->data;
-               gchar *ide = ADDRITEM_ID(objE);
-               if( ide ) {
-                       if( strcmp( ide, eid ) == 0 ) {
-                               email = ( ItemEMail * ) objE;
-                       }
-               }
-               node = g_list_next( node );
-       }
-
-       if( email ) {
-               /* Remove email from person's address list */
-               if( person->listEMail ) {
-                       person->listEMail = g_list_remove( person->listEMail, email );
-               }
-               /* Unlink reference to person. */
-               ADDRITEM_PARENT(email) = NULL;
-       }
-       return email;
-}
-
-/*
-* Remove email address for specified.
-* param: person        Person.
-*        email EMail to remove.
-* return: EMail object, or NULL if not found. Note that object should still be freed.
-*/
+/**
+ * Remove email address for specified person.
+ * \param  person Person.
+ * \param  email  EMail to remove.
+ * \return EMail object, or <i>NULL</i> if not found. Note that object should
+ *         still be freed after calling this method.
+ */
 ItemEMail *addritem_person_remove_email( ItemPerson *person, ItemEMail *email ) {
        gboolean found = FALSE;
        GList *node;
@@ -458,50 +552,29 @@ ItemEMail *addritem_person_remove_email( ItemPerson *person, ItemEMail *email )
        return NULL;
 }
 
-/*
-* Add user attribute to person.
-* return: TRUE if item added.
-*/
-void addritem_person_add_attribute( ItemPerson *person, UserAttribute *attrib ) {
+/**
+ * Add user attribute to specified person.
+ * \param  person Person.
+ * \param  attrib Attribute to add.
+ * \return <i>TRUE</i> if item added.
+ */
+void addritem_person_add_attribute(
+                       ItemPerson *person, UserAttribute *attrib )
+{
        g_return_if_fail( person != NULL );
        person->listAttrib = g_list_append( person->listAttrib, attrib );
 }
 
-/*
-* Return attribute with specified ID.
-* param: person Person object.
-*        aid    Attribute ID.
-* return: UserAttribute object, or NULL if not found. Note that object should still be freed.
-*/
-UserAttribute *addritem_person_get_attribute( ItemPerson *person, const gchar *aid ) {
-       UserAttribute *attrib = NULL;
-       GList *node;
-
-       g_return_val_if_fail( person != NULL, NULL );
-       if( aid == NULL || *aid == '\0' ) return NULL;
-
-       /* Look for attribute */
-       node = person->listAttrib;
-       while( node ) {
-               UserAttribute *attr = node->data;
-               gchar *ida = attr->uid;
-               if( ida ) {
-                       if( strcmp( ida, aid ) == 0 ) {
-                               attrib = attr;
-                       }
-               }
-               node = g_list_next( node );
-       }
-       return attrib;
-}
-
-/*
-* Remove attribute from person.
-* param: person Person object.
-*        aid    Attribute ID.
-* return: UserAttribute object, or NULL if not found. Note that object should still be freed.
-*/
-UserAttribute *addritem_person_remove_attrib_id( ItemPerson *person, const gchar *aid ) {
+/**
+ * Remove attribute with specified ID from person.
+ * \param  person Person object.
+ * \param  aid    Attribute ID to remove.
+ * \return UserAttribute object, or <i>NULL</i> if not found. Note that
+ *         attribute object should still be freed after calling this method.
+ */
+UserAttribute *addritem_person_remove_attrib_id(
+                       ItemPerson *person, const gchar *aid )
+{
        UserAttribute *attrib = NULL;
        GList *node;
 
@@ -528,13 +601,16 @@ UserAttribute *addritem_person_remove_attrib_id( ItemPerson *person, const gchar
        return attrib;
 }
 
-/*
-* Remove attribute from person.
-* param: person        Person.
-*        attrib        Attribute to remove.
-* return: UserAttribute object. Note that object should still be freed.
-*/
-UserAttribute *addritem_person_remove_attribute( ItemPerson *person, UserAttribute *attrib ) {
+/**
+ * Remove attribute from person.
+ * \param  person Person.
+ * \param  attrib Attribute to remove.
+ * \return UserAttribute object to remove. Note that attribute object should
+ *         still be freed.
+ */
+UserAttribute *addritem_person_remove_attribute(
+                       ItemPerson *person, UserAttribute *attrib )
+{
        gboolean found = FALSE;
        GList *node;
 
@@ -560,9 +636,10 @@ UserAttribute *addritem_person_remove_attribute( ItemPerson *person, UserAttribu
        return attrib;
 }
 
-/*
-* Create new address book group.
-*/
+/**
+ * Create new address book group object.
+ * \return Initialized group object.
+ */
 ItemGroup *addritem_create_item_group( void ) {
        ItemGroup *group;
 
@@ -577,11 +654,11 @@ ItemGroup *addritem_create_item_group( void ) {
        return group;
 }
 
-/*
-* Copy address book group.
-* Enter:  item Group to copy.
-* Return: A copy of the group. 
-*/
+/**
+ * Copy (deep copy) address book group.
+ * \param  item Group to copy.
+ * \return Copy of the group object, or <i>NULL</i> if null argument supplied.
+ */
 ItemGroup *addritem_copy_item_group( ItemGroup *item ) {
        ItemGroup *itemNew;
 
@@ -594,22 +671,19 @@ ItemGroup *addritem_copy_item_group( ItemGroup *item ) {
        return itemNew;
 }
 
-/*
-* Specify name to be used.
-*/
-void addritem_group_set_id( ItemGroup *group, const gchar *value ) {
-       ADDRITEM_ID(group) = mgu_replace_string( ADDRITEM_ID(group), value );
-}
+/**
+ * Specify name to be used for group.
+ * \param group Group object.
+ * \param value Name of group.
+ */
 void addritem_group_set_name( ItemGroup *group, const gchar *value ) {
        ADDRITEM_NAME(group) = mgu_replace_string( ADDRITEM_NAME(group), value );
 }
-void addritem_group_set_remarks( ItemGroup *group, const gchar *value ) {
-       group->remarks = mgu_replace_string( group->remarks, value );
-}
 
-/*
-* Free address group.
-*/
+/**
+ * Free address group object.
+ * \param group Group to free.
+ */
 void addritem_free_item_group( ItemGroup *group ) {
        g_return_if_fail( group != NULL );
 
@@ -631,10 +705,14 @@ void addritem_free_item_group( ItemGroup *group ) {
        g_free( group );
 }
 
-/*
-* Add EMail address to group.
-* return: TRUE if item added.
-*/
+/**
+ * Add EMail address to group. Note that a reference to an E-Mail item is
+ * added to a group. A person object is the only container that for an
+ * address.
+ * \param  group Group.
+ * \param  email E-Mail object.
+ * \return <i>TRUE</i> if email item added.
+ */
 gboolean addritem_group_add_email( ItemGroup *group, ItemEMail *email ) {
        GList *node;
 
@@ -650,44 +728,22 @@ gboolean addritem_group_add_email( ItemGroup *group, ItemEMail *email ) {
        return TRUE;
 }
 
-/*
-* Remove email address for specified group.
-* param: group Group from which to remove address.
-*        email EMail to remove
-* return: EMail object, or NULL if email not found in group. Note that this object is
-* referenced (linked) to a group and should *NOT* be freed. This object should only be
-* freed after removing from a person.
-*/
-ItemEMail *addritem_group_remove_email( ItemGroup *group, ItemEMail *email ) {
-       if( group && email ) {
-               GList *node = group->listEMail;
-               while( node ) {
-                       if( node->data == email ) {
-                               group->listEMail = g_list_remove( group->listEMail, email );
-                               return email;
-                       }
-                       node = g_list_next( node );
-               }
-       }
-       return NULL;
-}
-
-/*
-* Remove email address for specified group and ID.
-* param: group Group from which to remove address.
-*        eid   EMail ID.
-* return: EMail object, or NULL if email not found in group. Note that this object is
-* referenced (linked) to a group and should *NOT* be freed. This object should only be
-* freed after removing from a person.
-*/
-ItemEMail *addritem_group_remove_email_id( ItemGroup *group, const gchar *eid ) {
-       if( group ) {
-               GList *node = group->listEMail;
+/**
+ * Remove person object for specified group.
+ * \param  group Group from which to remove address.
+ * \param  email EMail to remove
+ * \return EMail object, or <i>NULL if email not found in group. Note that
+ *         this object is referenced (linked) to a group and should *NOT*
+ *         be freed. An E-Mail object object should only be freed after
+ *         removing from a person.
+ */
+ItemPerson *addritem_folder_remove_person( ItemFolder *group, ItemPerson *person ) {
+       if( group && person ) {
+               GList *node = group->listPerson;
                while( node ) {
-                       ItemEMail *email = ( ItemEMail * ) node->data;
-                       if( strcmp( ADDRITEM_ID( email ), eid ) == 0 ) {
-                               group->listEMail = g_list_remove( group->listEMail, email );
-                               return email;
+                       if( node->data == person ) {
+                               group->listPerson = g_list_remove( group->listPerson, person );
+                               return person;
                        }
                        node = g_list_next( node );
                }
@@ -695,9 +751,11 @@ ItemEMail *addritem_group_remove_email_id( ItemGroup *group, const gchar *eid )
        return NULL;
 }
 
-/*
-* Print address group item.
-*/
+/**
+ * Print address group item for debug.
+ * \param group  Group to print.
+ * \param stream Output stream.
+ */
 void addritem_print_item_group( ItemGroup *group, FILE *stream ) {
        GList *node;
        ItemPerson *person;
@@ -727,9 +785,10 @@ void addritem_print_item_group( ItemGroup *group, FILE *stream ) {
        fprintf( stream, "\t***\n" );
 }
 
-/*
-* Create new address folder.
-*/
+/**
+ * Create new address folder.
+ * \return Initialized address folder object.
+ */
 ItemFolder *addritem_create_item_folder( void ) {
        ItemFolder *folder;
        folder = g_new0( ItemFolder, 1 );
@@ -744,14 +803,18 @@ ItemFolder *addritem_create_item_folder( void ) {
        folder->listFolder = NULL;
        folder->listPerson = NULL;
        folder->listGroup = NULL;
+       folder->folderType = ADDRFOLDER_NONE;
+       folder->folderData = NULL;
+       folder->isHidden = FALSE;
        return folder;
 }
 
-/*
-* Copy address book folder.
-* Enter:  item Folder to copy.
-* Return: A copy of the folder. 
-*/
+/**
+ * Copy address book folder. Note that only the folder and not its contents are
+ * copied.
+ * \param  item Folder to copy.
+ * \return A copy of the folder, or <i>NULL</i> if null argument supplied.
+ */
 ItemFolder *addritem_copy_item_folder( ItemFolder *item ) {
        ItemFolder *itemNew;
 
@@ -759,28 +822,44 @@ ItemFolder *addritem_copy_item_folder( ItemFolder *item ) {
        if( item ) {
                itemNew = addritem_create_item_folder();
                ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) );
+               itemNew->folderType = item->folderType;
        }
        return itemNew;
 }
 
-/*
-* Specify name to be used.
-*/
-void addritem_folder_set_id( ItemFolder *folder, const gchar *value ) {
-       ADDRITEM_ID(folder) = mgu_replace_string( ADDRITEM_ID(folder), value );
-}
+/**
+ * Specify name to be used for folder.
+ * \param folder Folder.
+ * \param value  Name.
+ */
 void addritem_folder_set_name( ItemFolder *folder, const gchar *value ) {
        ADDRITEM_NAME(folder) = mgu_replace_string( ADDRITEM_NAME(folder), value );
 }
+
+/**
+ * Specify remarks to be used for folder.
+ * \param folder Folder.
+ * \param value  Remarks.
+ */
 void addritem_folder_set_remarks( ItemFolder *folder, const gchar *value ) {
        folder->remarks = mgu_replace_string( folder->remarks, value );
 }
 
-/*
-* Free address folder. Note: this does not free up the lists of children
-* (folders, groups and person). This should be done prior to calling this
-* function.
-*/
+/**
+ * Specify visibility of folder.
+ * \param folder Folder.
+ * \param value  Set to <code>TRUE</code> to hide folder.
+ */
+void addritem_folder_set_hidden( ItemFolder *folder, const gboolean value ) {
+       folder->isHidden = value;
+}
+
+/**
+ * Free address folder. Note: this does not free up the lists of children
+ * (folders, groups and person). This should be done prior to calling this
+ * function.
+ * \param folder Folder to free.
+ */
 void addritem_free_item_folder( ItemFolder *folder ) {
        g_return_if_fail( folder != NULL );
 
@@ -802,16 +881,20 @@ void addritem_free_item_folder( ItemFolder *folder ) {
        folder->listFolder = NULL;
        folder->listGroup = NULL;
        folder->listPerson = NULL;
+       folder->folderType = ADDRFOLDER_NONE;
+       folder->folderData = NULL;
+       folder->isHidden = FALSE;
 
        g_free( folder );
 }
 
-/*
-* Free up folders recursively. Note: this does not free up the lists of children
-* (folders, groups and person). This should be done prior to calling this
-* function.
-*/
-void addritem_free_item_folder_recurse( ItemFolder *parent ) {
+/**
+ * Free up folders recursively. Note: this only frees up the lists of
+ * children and *NOT* the children objects (folders, groups and person).
+ * This should be done prior to calling this function.
+ * \param parent Parent folder object to be processed.
+ */
+static void addritem_free_item_folder_recurse( ItemFolder *parent ) {
        GList *node = parent->listFolder;
 
        while( node ) {
@@ -827,28 +910,12 @@ void addritem_free_item_folder_recurse( ItemFolder *parent ) {
        parent->listFolder = NULL;
 }
 
-/*
-* Free up list of person in specified folder.
-*/
-void addritem_folder_free_person( ItemFolder *folder ) {
-       GList *node;
-
-       g_return_if_fail( folder != NULL );
-       
-       /* Free up folder of persons. */
-       node = folder->listPerson;
-       while( node ) {
-               ItemPerson *person = node->data;
-               addritem_free_item_person( person );
-               person = NULL;
-               node = g_list_next( node );
-       }
-}
-
-/*
-* Add person into folder.
-* return: TRUE if person added.
-*/
+/**
+ * Add person into folder.
+ * \param  folder Folder.
+ * \param  item   Person to add.
+ * \return <i>TRUE</i> if person added.
+ */
 gboolean addritem_folder_add_person( ItemFolder *folder, ItemPerson *item ) {
        g_return_val_if_fail( folder != NULL, FALSE );
        g_return_val_if_fail( item != NULL, FALSE );
@@ -858,10 +925,12 @@ gboolean addritem_folder_add_person( ItemFolder *folder, ItemPerson *item ) {
        return TRUE;
 }
 
-/*
-* Add folder into folder.
-* return: TRUE if folder added.
-*/
+/**
+ * Add folder into folder.
+ * \param  folder Folder.
+ * \param  item   Folder to add.
+ * \return <i>TRUE</i> if folder added.
+ */
 gboolean addritem_folder_add_folder( ItemFolder *folder, ItemFolder *item ) {
        g_return_val_if_fail( folder != NULL, FALSE );
        g_return_val_if_fail( item != NULL, FALSE );
@@ -871,10 +940,12 @@ gboolean addritem_folder_add_folder( ItemFolder *folder, ItemFolder *item ) {
        return TRUE;
 }
 
-/*
-* Add group into folder.
-* return: TRUE if folder added.
-*/
+/**
+ * Add group into folder.
+ * \param  folder Folder.
+ * \param  item   Group to add.
+ * \return <i>TRUE</i> if group added.
+ */
 gboolean addritem_folder_add_group( ItemFolder *folder, ItemGroup *item ) {
        g_return_val_if_fail( folder != NULL, FALSE );
        g_return_val_if_fail( item != NULL, FALSE );
@@ -884,9 +955,11 @@ gboolean addritem_folder_add_group( ItemFolder *folder, ItemGroup *item ) {
        return TRUE;
 }
 
-/*
-* Print address folder item.
-*/
+/**
+ * Print address folder item contents for debug.
+ * \param folder Folder to process.
+ * \param stream Output stream.
+ */
 void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) {
        GList *node;
        /* ItemPerson *person; */
@@ -899,6 +972,8 @@ void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) {
        fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(folder) );
        fprintf( stream, "\tnam: '%s'\n", ADDRITEM_NAME(folder) );
        fprintf( stream, "\trem: '%s'\n", folder->remarks );
+       fprintf( stream, "\ttyp: %d\n", folder->folderType );
+       fprintf( stream, "\thid: %s\n", folder->isHidden ? "hidden" : "visible" );
        fprintf( stream, "\t---\n" );
        parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
        if( parent ) {
@@ -956,36 +1031,14 @@ void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) {
        fprintf( stream, "\t###\n" );
 }
 
-/*
-* Print address item.
-*/
-void addritem_print_item( AddrItemObject *aio, FILE *stream ) {
-       g_return_if_fail( aio != NULL );
-
-       if( aio->type == ITEMTYPE_PERSON ) {
-               ItemPerson *item = ( ItemPerson * ) aio;
-               addritem_print_item_person( item, stream );
-       }
-       else if( aio->type == ITEMTYPE_EMAIL ) {
-               ItemEMail *item = ( ItemEMail * ) aio;
-               addritem_print_item_email( item, stream );
-       }
-       else if( aio->type == ITEMTYPE_GROUP ) {
-               ItemGroup *item = ( ItemGroup * ) aio;
-               addritem_print_item_group( item, stream );
-       }
-       else if( aio->type == ITEMTYPE_FOLDER ) {
-               ItemFolder *item = ( ItemFolder * ) aio;
-               addritem_print_item_folder( item, stream );
-       }
-}
-
-/*
-* Return link list of persons for specified folder. Note that the list contains
-* references to items and should be g_free() when done. Do *NOT* attempt to use the
-* addritem_free_xxx() functions... this will destroy the addressbook data!
-* Return: List of items, or NULL if none.
-*/
+/**
+ * Return link list of persons for specified folder. Note that the list contains
+ * references to items and should be g_free() when done. Do *NOT* attempt to use the
+ * addritem_free_xxx() functions... this will destroy the addressbook data!
+ *
+ * \param  folder Folder to process.
+ * \return List of items, or <i>NULL</i> if none.
+ */
 GList *addritem_folder_get_person_list( ItemFolder *folder ) {
        GList *list = NULL;
        GList *node = NULL;
@@ -1001,12 +1054,14 @@ GList *addritem_folder_get_person_list( ItemFolder *folder ) {
        return list;
 }
 
-/*
-* Return link list of groups for specified folder. Note that the list contains
-* references to items and should be g_free() when done. Do *NOT* attempt to use the
-* addritem_free_xxx() functions... this will destroy the addressbook data!
-* Return: List of items, or NULL if none.
-*/
+/**
+ * Return link list of groups for specified folder. Note that the list contains
+ * references to items and should be g_free() when done. Do *NOT* attempt to use the
+ * addritem_free_xxx() functions... this will destroy the addressbook data!
+ *
+ * \param  folder Folder to process.
+ * \return List of items, or <i>NULL</i> if none.
+ */
 GList *addritem_folder_get_group_list( ItemFolder *folder ) {
        GList *list = NULL;
        GList *node = NULL;
@@ -1022,14 +1077,18 @@ GList *addritem_folder_get_group_list( ItemFolder *folder ) {
        return list;
 }
 
-/*
-* Move person's email item.
-* param: person     Person.
-*        itemMove   Item to move.
-*        itemTarget Target item before which to move item.
-*/
+/**
+ * Move person's email item.
+ * \param  person     Person.
+ * \param  itemMove   Item to move.
+ * \param  itemTarget Target item before which to move item.
+ * \return Reference to item that was moved, or <i>NULL</i> if null arguments
+ *         supplied.
+ */
 
-ItemEMail *addritem_move_email_before( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget ) {
+ItemEMail *addritem_move_email_before(
+               ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget )
+{
        gint posT, posM;
 
        g_return_val_if_fail( person != NULL, NULL );
@@ -1047,13 +1106,17 @@ ItemEMail *addritem_move_email_before( ItemPerson *person, ItemEMail *itemMove,
        return itemMove;
 }
 
-/*
-* Move person's email item.
-* param: person     Person.
-*        itemMove   Item to move.
-*        itemTarget Target item after which to move item.
-*/
-ItemEMail *addritem_move_email_after( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget ) {
+/**
+ * Move person's email item.
+ * \param  person    Person.
+ * \param  itemMove  Item to move.
+ * \param  itemTarget Target item after which to move item.
+ * \return Reference to item that was moved, or <i>NULL</i> if null arguments
+ *         supplied.
+ */
+ItemEMail *addritem_move_email_after(
+               ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget )
+{
        gint posT, posM;
 
        g_return_val_if_fail( person != NULL, NULL );
@@ -1073,7 +1136,7 @@ ItemEMail *addritem_move_email_after( ItemPerson *person, ItemEMail *itemMove, I
 
 /**
  * Parse first and last names for person from common name.
- * Enter: person Person to process.
+ * \param person Person to process.
  */
 void addritem_parse_first_last( ItemPerson *person ) {
        gchar *name;
@@ -1110,21 +1173,80 @@ void addritem_parse_first_last( ItemPerson *person ) {
                }
        }
 
-       if( person->firstName ) {
-               g_free( person->firstName );
-       }
+       g_free( person->firstName );
        person->firstName = fName;
        if( person->firstName )
                g_strstrip( person->firstName );
 
-       if( person->lastName ) {
-               g_free( person->lastName );
-       }
+       g_free( person->lastName );
        person->lastName = lName;
        if( person->lastName )
                g_strstrip( person->lastName );
 }
 
+/**
+ * Build a path of all ancestor folders for specified folder.
+ * \param  folder Folder.
+ * \param  seq    Path sequence, FALSE top down, TRUE bottom up.
+ * \return List of folders from the top down.
+ */
+GList *addritem_folder_path( const ItemFolder *folder, const gboolean seq ) {
+       GList *list;
+       AddrItemObject *item;
+
+       list = NULL;
+       item = ( AddrItemObject * ) folder;
+       if( seq ) {
+               while( item ) {
+                       list = g_list_prepend( list, item );
+                       item = ADDRITEM_PARENT( item );
+               }
+       }
+       else {
+               while( item ) {
+                       list = g_list_append( list, item );
+                       item = ADDRITEM_PARENT( item );
+               }
+       }
+       return list;
+}
+
+/**
+ * Format E-Mail address.
+ * \param email EMail item to format.
+ * \return Formatted string. Should be freed after use.
+ */
+gchar *addritem_format_email( ItemEMail *email ) {
+       gchar *address;
+       gchar *name;
+       ItemPerson *person;
+
+       address = NULL;
+       name = NULL;
+       if( ADDRITEM_NAME( email ) ) {
+               if( strlen( ADDRITEM_NAME( email ) ) ) {
+                       name = ADDRITEM_NAME( email );
+               }
+       }
+       if( ! name ) {
+               person = ( ItemPerson * ) ADDRITEM_PARENT( email );
+               name = ADDRITEM_NAME( person );
+       }
+
+       if( name ) {
+               if( strchr_with_skip_quote( name, '"', ',' ) ) {
+                       address = g_strdup_printf( "\"%s\" <%s>", name, email->address );
+               }
+               else {
+                       address = g_strdup_printf( "%s <%s>", name, email->address );
+               }
+       }
+       else {
+               address = g_strdup_printf( "%s", email->address );
+       }
+       return address;
+}
+
 /*
 * End of Source.
 */