soylent r268 - trunk/libsoylent
- From: svenp svn gnome org
- To: svn-commits-list gnome org
- Subject: soylent r268 - trunk/libsoylent
- Date: Mon, 11 Aug 2008 21:33:46 +0000 (UTC)
Author: svenp
Date: Mon Aug 11 21:33:46 2008
New Revision: 268
URL: http://svn.gnome.org/viewvc/soylent?rev=268&view=rev
Log:
fixed: illegal / unknown vCard attributes are handled with a warning
fixed: eattributes are now handled correctly (1 SlAttribute value <-> 1 eattribute)
fixed: format of eattribute-values is now handled correctly
implemented attribute signal-handling
Modified:
trunk/libsoylent/sl-attribute-eds.c
trunk/libsoylent/sl-attribute-eds.h
Modified: trunk/libsoylent/sl-attribute-eds.c
==============================================================================
--- trunk/libsoylent/sl-attribute-eds.c (original)
+++ trunk/libsoylent/sl-attribute-eds.c Mon Aug 11 21:33:46 2008
@@ -21,9 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "soylent.h"
-#include "sl-attribute-eds.h"
-#include "sl-person.h"
+#include "sl-mutual-inclusion.h"
+#include "sl-priv-util.h"
#include "sl-attributes.h"
struct _SlAttributePriv
@@ -31,7 +30,7 @@
SlEntity *entity;
const gchar *name;
GList *values;
- EVCardAttribute *eattr;
+ GList *eattributes;
};
static GObjectClass *attribute_parent_class = NULL;
@@ -129,16 +128,18 @@
return sl_priv_util_list_contains (ignored, (gpointer) eattrname, g_str_equal);
}
+static GHashTable *eattrname_to_name_map = NULL;
+static GHashTable *name_to_eattrname_map = NULL;
+
const gchar *
sl_attribute_name_to_eattrname (const gchar *name)
{
- static GHashTable *name_to_eattrname_map = NULL;
if (name_to_eattrname_map == NULL)
{
name_to_eattrname_map = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (name_to_eattrname_map, SL_ATTR_ID, EVC_UID);
g_hash_table_insert (name_to_eattrname_map, SL_ATTR_NAME, EVC_N);
- g_hash_table_insert (name_to_eattrname_map, SL_ATTR_FAMILY_NAME, EVC_FN);
+ g_hash_table_insert (name_to_eattrname_map, SL_ATTR_FULL_NAME, EVC_FN);
g_hash_table_insert (name_to_eattrname_map, SL_ATTR_NICK, EVC_NICKNAME);
g_hash_table_insert (name_to_eattrname_map, SL_ATTR_GROUP, EVC_CATEGORIES);
g_hash_table_insert (name_to_eattrname_map, SL_ATTR_ADDRESS, EVC_ADR);
@@ -169,13 +170,12 @@
const gchar *
sl_attribute_eattrname_to_name (const gchar *eattrname)
{
- static GHashTable *eattrname_to_name_map = NULL;
if (eattrname_to_name_map == NULL)
{
eattrname_to_name_map = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (eattrname_to_name_map, EVC_UID, SL_ATTR_ID);
g_hash_table_insert (eattrname_to_name_map, EVC_N, SL_ATTR_NAME);
- g_hash_table_insert (eattrname_to_name_map, EVC_FN, SL_ATTR_FAMILY_NAME);
+ g_hash_table_insert (eattrname_to_name_map, EVC_FN, SL_ATTR_FULL_NAME);
g_hash_table_insert (eattrname_to_name_map, EVC_NICKNAME, SL_ATTR_NICK);
g_hash_table_insert (eattrname_to_name_map, EVC_CATEGORIES, SL_ATTR_GROUP);
g_hash_table_insert (eattrname_to_name_map, EVC_ADR, SL_ATTR_ADDRESS);
@@ -196,12 +196,21 @@
const gchar *name = g_hash_table_lookup (eattrname_to_name_map, eattrname);
if (name == NULL)
{
+
/* TODO: this leaks, cause name must be freed somehow */
if (!g_str_has_prefix (eattrname, "X-"))
{
- g_error ("EDS: illegal vCard field: %s", eattrname);
+ /* workaround for illegal vCard fields */
+ g_warning ("EDS: illegal or not implemented vCard field: %s", eattrname);
+ name = g_utf8_strdown (eattrname, -1);
+ if (name_to_eattrname_map == NULL) sl_attribute_name_to_eattrname ("foo");
+ g_hash_table_insert (eattrname_to_name_map, (gchar *) eattrname, (gchar *) name);
+ g_hash_table_insert (name_to_eattrname_map, (gchar *) name, (gchar *) eattrname);
+ }
+ else
+ {
+ name = g_utf8_strdown (&eattrname[2], -1);
}
- name = g_utf8_strdown (&eattrname[2], -1);
}
return name;
}
@@ -211,10 +220,13 @@
{
self->priv->entity = NULL;
self->priv->name = name;
- self->priv->eattr = e_vcard_attribute_new (NULL, sl_attribute_name_to_eattrname (name));
+ self->priv->eattributes = NULL;
self->priv->values = NULL;
if (value != NULL)
{
+ /* TODO: write value to eattr */
+ EVCardAttribute *eattr = e_vcard_attribute_new (NULL, sl_attribute_name_to_eattrname (name));
+ self->priv->eattributes = g_list_append (self->priv->eattributes, eattr);
self->priv->values = g_list_append (self->priv->values, value);
}
}
@@ -224,6 +236,7 @@
GList *values)
{
sl_attribute_constr (self, name, NULL);
+ /* TODO: write value to eattr */
self->priv->values = values;
}
@@ -233,13 +246,26 @@
/* TODO: all attributes twice in memory, once in their "vcard form" and once
* in their "runtime form". This is clearly not optimal. */
self->priv->entity = NULL;
- self->priv->eattr = eattr;
+ self->priv->eattributes = NULL;
self->priv->values = NULL;
self->priv->name = sl_attribute_eattrname_to_name (e_vcard_attribute_get_name (eattr));
sl_debug_attribute ("creating attribute \"%s\" from eattribute", self->priv->name);
- sl_attribute_set_all_from_eattr (self, eattr);
+ sl_attribute_add_from_eattr (self, eattr);
+}
+
+void
+sl_attribute_constr_with_eattributes (SlAttribute *self, GList *eattributes)
+{
+ EVCardAttribute *eattr = eattributes->data;
+ sl_attribute_constr_with_eattr (self, eattr);
+ eattributes = eattributes->next;
+ for (; eattributes != NULL; eattributes = eattributes->next)
+ {
+ eattr = eattributes->data;
+ sl_attribute_add_from_eattr (self, eattr);
+ }
}
SlAttribute *
@@ -274,39 +300,63 @@
return self;
}
+SlAttribute *
+sl_attribute_new_with_eattributes (GList *eattributes)
+{
+ SlAttribute *self = g_object_new (SL_ATTRIBUTE_TYPE, NULL);
+ sl_attribute_constr_with_eattributes (self, eattributes);
+ return self;
+}
+
void
-sl_attribute_set_all_from_eattr (SlAttribute *self, EVCardAttribute *eattr)
+sl_attribute_add_from_eattr (SlAttribute *self, EVCardAttribute *eattr)
{
- self->priv->values = NULL;
+ sl_debug_attribute ("adding eattribute to attribute \"%s\"", self->priv->name);
- GList *evalues = e_vcard_attribute_get_values (eattr);
- gpointer evalue = NULL;
- for (; evalues != NULL; evalues = evalues->next)
+ GList *evalue_tokens = e_vcard_attribute_get_values (eattr);
+ GString *evalue = g_string_new ("");
+ for (; evalue_tokens != NULL; evalue_tokens = evalue_tokens->next)
{
- evalue = evalues->data;
- gpointer value = NULL;
-
- /* TODO: install attribute-definition if attribute is unknown? would
- * solve the problem that reading is done in bytes while reading is still
- * done with strings
-
- GList* encodings = e_vcard_attribute_get_param (eattr, EVC_ENCODING);
- if (encodings != NULL)
+ gchar *evalue_token = evalue_tokens->data;
+ if (!g_str_equal (evalue->str, ""))
{
- g_debug ("now I'm decoding some base64 stuff!");*/
- /* TODO: handle other encodings
- GByteArray *bytes = g_byte_array_new ();
- bytes->data = g_base64_decode (evalue, &bytes->len);
- value = sl_attribute_mapper_read (self->priv->name, bytes, SL_ATTRIBUTE_SYS_TYPE_BYTE);*/
- /* TODO: Free bytes here. For the moment the bytes are just passed
- * through the mapper, so they are still needed later
+ g_string_append (evalue, ";");
}
- else
- {*/
- value = sl_attribute_mapper_read (self->priv->name, evalue);
- /*}*/
-
- self->priv->values = g_list_append (self->priv->values, value);
+ g_string_append (evalue, evalue_token);
+ }
+
+ gpointer value = sl_attribute_mapper_read (self->priv->name, evalue->str);
+ self->priv->values = g_list_append (self->priv->values, value);
+ self->priv->eattributes = g_list_append (self->priv->eattributes, eattr);
+}
+
+void
+sl_attribute_update_eattributes (SlAttribute *self, GList *eattributes)
+{
+ sl_debug_attribute ("updating eattributes of attribute \"%s\"", self->priv->name);
+ /* TODO: this method may only be called if eattributes have exactly the same
+ * order */
+ g_list_free (self->priv->eattributes);
+ self->priv->eattributes = g_list_copy (eattributes);
+}
+
+void
+sl_attribute_set_all_from_eattributes (SlAttribute *self, GList *eattributes)
+{
+ GList *values = self->priv->values;
+ for (; values != NULL; values = values->next)
+ {
+ sl_attribute_cleanup (self->priv->name, values->data);
+ }
+ g_list_free (values);
+ self->priv->values = NULL;
+
+ g_list_free (self->priv->eattributes);
+ self->priv->eattributes = NULL;
+
+ for (; eattributes != NULL; eattributes = eattributes->next)
+ {
+ sl_attribute_add_from_eattr (self, eattributes->data);
}
}
@@ -319,88 +369,257 @@
void
sl_attribute_set_entity (SlAttribute *self, SlEntity *entity)
{
- self->priv->entity = g_object_ref (entity);
+ if (entity != NULL)
+ {
+ g_object_ref (entity);
+ }
+ self->priv->entity = entity;
+}
+
+GList *sl_attribute_get_eattributes (SlAttribute *self)
+{
+ return self->priv->eattributes;
+}
+
+EVCardAttribute *
+sl_attribute_create_eattr (SlAttribute *self, gpointer value)
+{
+ sl_debug_attribute ("creating eattribute from value of \"%s\"", self->priv->name);
+
+ gchar *evalue = sl_attribute_mapper_write (self->priv->name, value);
+ const gchar *eattrname = sl_attribute_name_to_eattrname (self->priv->name);
+ EVCardAttribute *eattr = e_vcard_attribute_new (NULL, eattrname);
+
+ gchar **tokens = g_strsplit (evalue, ";", 0);
+ gchar **tokenp = NULL;
+ for (tokenp = tokens; *tokenp != NULL; tokenp++)
+ {
+ e_vcard_attribute_add_value (eattr, *tokenp);
+ }
+ g_free (tokens);
+
+ if (self->priv->entity != NULL)
+ {
+ EContact *econtact = sl_entity_get_econtact (self->priv->entity);
+ e_vcard_add_attribute (E_VCARD (econtact), eattr);
+ }
+
+ return eattr;
+}
+
+void
+sl_attribute_add (SlAttribute *self, gpointer value)
+{
+ sl_attribute_add_emit (self, value, TRUE);
+}
+
+void
+sl_attribute_add_emit (SlAttribute *self, gpointer value, gboolean emit)
+{
+ EVCardAttribute *eattr = sl_attribute_create_eattr (self, value);
+ self->priv->values = g_list_append (self->priv->values, value);
+ self->priv->eattributes = g_list_append (self->priv->eattributes, eattr);
+
+ if (emit)
+ {
+ sl_attribute_emit_modified (self);
+ }
}
-EVCardAttribute *sl_attribute_get_eattr (SlAttribute *self)
+gpointer
+sl_attribute_get (SlAttribute *self)
{
- return self->priv->eattr;
+ return sl_attribute_get_at (self, 0);
}
-void sl_attribute_set (SlAttribute *self, gpointer value)
+void
+sl_attribute_set (SlAttribute *self, gpointer value)
{
- /* TODO: temporary add, but should be set_at (0) */
- sl_attribute_add (self, value);
+ if (!sl_attribute_set_at (self, 0, value))
+ {
+ sl_attribute_add (self, value);
+ }
}
-gpointer sl_attribute_get (SlAttribute *self)
+gpointer
+sl_attribute_get_at (SlAttribute *self, gint index)
{
- if (self->priv->values == NULL)
+ GList *value_nth = g_list_nth (self->priv->values, index);
+ if (value_nth == NULL)
{
- sl_debug_attribute ("attribute \"%s\" has no value", sl_attribute_get_name (self));
return NULL;
}
- return self->priv->values->data;
+ else
+ {
+ return value_nth->data;
+ }
}
-void sl_attribute_add (SlAttribute *self, gpointer value)
+gboolean
+sl_attribute_set_at (SlAttribute *self, gint index, gpointer value)
{
- gpointer evalue = sl_attribute_mapper_write (self->priv->name, value);
-
- /* TODO: encode value if binary */
- self->priv->values = g_list_append (self->priv->values, value);
- e_vcard_attribute_add_value (self->priv->eattr, evalue);
- /* TODO: libebook crap: every ; seperates a value, so structs are just lists
- * of values. 2 structs is a list of double length... solutions: a) don't use
- * ; anymore for systypes and split before inserting in eattr. b) no idea*/
+ return sl_attribute_set_at_emit (self, index, value, TRUE);
}
-gboolean sl_attribute_set_at (SlAttribute *self, gint index, gpointer value)
+gboolean
+sl_attribute_set_at_emit (SlAttribute *self, gint index, gpointer value, gboolean emit)
{
- gpointer result = sl_attribute_mapper_write (self->priv->name, value);
-
- GList *evalues = e_vcard_attribute_get_values (self->priv->eattr);
- GList *evalue_nth = g_list_nth (evalues, index);
GList *value_nth = g_list_nth (self->priv->values, index);
- if (evalue_nth == NULL)
+ if (value_nth == NULL)
{
return FALSE;
}
- g_assert (value_nth != NULL);
- /* TODO: can I always free this? */
- g_free (evalue_nth->data);
- /* TODO: user has to free value, I don't know how */
-
+
+ sl_attribute_cleanup (self->priv->name, value_nth->data);
value_nth->data = value;
- evalue_nth->data = result;
+
+ return sl_attribute_modified_at_emit (self, index, emit);
+}
+gboolean
+sl_attribute_remove_at (SlAttribute *self, gint index)
+{
+ return sl_attribute_remove_at_emit (self, index, TRUE);
+}
+
+gboolean
+sl_attribute_remove_at_emit (SlAttribute *self, gint index, gboolean emit)
+{
+ gpointer value = sl_attribute_get_at (self, index);
+ GList *eattr_nth = g_list_nth (self->priv->eattributes, index);
+ if (value == NULL)
+ {
+ return FALSE;
+ }
+ g_assert (eattr_nth != NULL);
+ EVCardAttribute *eattr = eattr_nth->data;
+
+ self->priv->values = g_list_remove (self->priv->values, value);
+ sl_attribute_cleanup (self->priv->name, value);
+
+ self->priv->eattributes = g_list_remove (self->priv->eattributes, eattr);
+
+ if (self->priv->entity != NULL)
+ {
+ EContact *econtact = sl_entity_get_econtact (self->priv->entity);
+ e_vcard_remove_attribute (E_VCARD (econtact), eattr);
+ }
+
+ if (emit)
+ {
+ sl_attribute_emit_modified (self);
+ }
+
return TRUE;
}
-gpointer sl_attribute_get_at (SlAttribute *self, gint index)
+/**
+ * sl_attribute_get_all:
+ * @self: a #SlAttribute
+ *
+ * Returns a list of all values of the attribute @self.
+ *
+ * Returns: a list of all values of the attribute. It is owned by the attribute
+ * and should neither be modified nor freed. The list will reflect all changes
+ * of the attribute (e.g. if a value is added to the attribute).
+ */
+GList *
+sl_attribute_get_all (SlAttribute *self)
{
- g_warning("%s not implemented", __FUNCTION__);
- return NULL;
+ g_return_val_if_fail (self != NULL && SL_IS_ATTRIBUTE (self), NULL);
+ return self->priv->values;
}
-void sl_attribute_remove_at (SlAttribute *self, gint index)
+/**
+ * sl_attribute_set_all:
+ * @self: a #SlAttribute
+ * @values: a list of values
+ *
+ * Replaces all values of the attribute @self with @values.
+ */
+void
+sl_attribute_set_all (SlAttribute *self, GList *values)
{
- g_warning("%s not implemented", __FUNCTION__);
+ g_return_if_fail (self != NULL && SL_IS_ATTRIBUTE (self));
+
+ sl_attribute_remove_all_emit (self, FALSE);
+ for (; values != NULL; values = values->next)
+ {
+ sl_attribute_add_emit (self, values->data, FALSE);
+ }
}
-void sl_attribute_set_all (SlAttribute *self, GList *values)
+void
+sl_attribute_remove_all (SlAttribute *self)
{
- g_warning("%s not implemented", __FUNCTION__);
+ sl_attribute_remove_all_emit (self, TRUE);
}
-GList *sl_attribute_get_all (SlAttribute *self)
+void
+sl_attribute_remove_all_emit (SlAttribute *self, gboolean emit)
{
- return self->priv->values;
+ while (self->priv->values != NULL)
+ {
+ g_assert (sl_attribute_remove_at (self, 0));
+ }
+
+ if (emit)
+ {
+ sl_attribute_emit_modified (self);
+ }
}
-void sl_attribute_remove_all (SlAttribute *self)
+void
+sl_attribute_modified (SlAttribute *self)
{
- g_warning("%s not implemented", __FUNCTION__);
+ sl_attribute_modified_at (self, 0);
+}
+
+gboolean
+sl_attribute_modified_at (SlAttribute *self, gint index)
+{
+ return sl_attribute_modified_at_emit (self, index, TRUE);
+}
+
+gboolean
+sl_attribute_modified_at_emit (SlAttribute *self, gint index, gboolean emit)
+{
+ GList *value_nth = g_list_nth (self->priv->values, index);
+ GList *eattr_nth = g_list_nth (self->priv->eattributes, index);
+ if (value_nth == NULL)
+ {
+ return FALSE;
+ }
+ g_assert (eattr_nth != NULL);
+
+ EVCardAttribute *eattr = sl_attribute_create_eattr (self, value_nth->data);
+ if (self->priv->entity != NULL)
+ {
+ EContact *econtact = sl_entity_get_econtact (self->priv->entity);
+ e_vcard_remove_attribute (E_VCARD (econtact), eattr_nth->data);
+ }
+ eattr_nth->data = eattr;
+
+ if (emit)
+ {
+ sl_attribute_emit_modified (self);
+ }
+
+ return TRUE;
+}
+
+void
+sl_attribute_emit_modified (SlAttribute *self)
+{
+ g_return_if_fail (self != NULL && SL_IS_ATTRIBUTE (self));
+
+ /* TODO: implement signals for SlAttribute and SlPerson */
+ SlBook *book = NULL;
+ if (self->priv->entity != NULL && (book = sl_person_get_book (SL_PERSON (self->priv->entity))) != NULL)
+ {
+ /* TODO: old values? */
+ sl_book_emit_person_attribute_modified (book, SL_PERSON (self->priv->entity), self, NULL, TRUE);
+ }
}
gint
@@ -409,7 +628,8 @@
return g_list_length (self->priv->values);
}
-const gchar *sl_attribute_get_name (SlAttribute *self)
+const gchar *
+sl_attribute_get_name (SlAttribute *self)
{
return self->priv->name;
}
Modified: trunk/libsoylent/sl-attribute-eds.h
==============================================================================
--- trunk/libsoylent/sl-attribute-eds.h (original)
+++ trunk/libsoylent/sl-attribute-eds.h Mon Aug 11 21:33:46 2008
@@ -24,8 +24,7 @@
#ifndef SL_ATTRIBUTE_EDS_H
#define SL_ATTRIBUTE_EDS_H
-#include "sl-priv-util.h"
-#include "sl-entity-eds.h"
+#include "sl-mutual-inclusion.h"
#include <glib.h>
#include <glib-object.h>
@@ -60,37 +59,58 @@
GType sl_attribute_get_type (void);
+/* VCard / E-D-S related */
gboolean sl_is_ignored_eattr (const gchar *eattrname);
+const gchar *sl_attribute_name_to_eattrname (const gchar *name);
+const gchar *sl_attribute_eattrname_to_name (const gchar *eattrname);
+/* construction */
void sl_attribute_constr (SlAttribute *self, const gchar *name, gpointer value);
void sl_attribute_constr_with_values (SlAttribute *self, const gchar *name,
GList *values);
void sl_attribute_constr_with_eattr (SlAttribute *self, EVCardAttribute *eattr);
+void sl_attribute_constr_with_eattributes (SlAttribute *self, GList *eattributes);
SlAttribute *sl_attribute_new (const gchar *name, gpointer value);
SlAttribute *sl_attribute_new_empty (const gchar *name);
SlAttribute *sl_attribute_new_with_values (const gchar *name, GList *values);
SlAttribute *sl_attribute_new_with_eattr (EVCardAttribute *eattr);
-void sl_attribute_set_all_from_eattr (SlAttribute *self, EVCardAttribute *eattr);
-
-SlEntity *sl_attribute_get_entity (SlAttribute *self);
-void sl_attribute_set_entity (SlAttribute *self, SlEntity *entity);
-EVCardAttribute *sl_attribute_get_eattr (SlAttribute *self);
+SlAttribute *sl_attribute_new_with_eattributes (GList *eattributes);
-const gchar *sl_attribute_name_to_eattrname (const gchar *name);
-const gchar *sl_attribute_eattrname_to_name (const gchar *eattrname);
+/* getters & setters */
+const gchar *sl_attribute_get_name (SlAttribute *self);
+gint sl_attribute_get_value_count (SlAttribute *self);
-void sl_attribute_set (SlAttribute *self, gpointer value);
+/* value manipulation */
+void sl_attribute_add (SlAttribute *self, gpointer value);
gpointer sl_attribute_get (SlAttribute *self);
-gboolean sl_attribute_set_at (SlAttribute *self, gint index, gpointer value);
+void sl_attribute_set (SlAttribute *self, gpointer value);
gpointer sl_attribute_get_at (SlAttribute *self, gint index);
-void sl_attribute_remove_at (SlAttribute *self, gint index);
-void sl_attribute_add (SlAttribute *self, gpointer value);
+gboolean sl_attribute_set_at (SlAttribute *self, gint index, gpointer value);
+gboolean sl_attribute_remove_at (SlAttribute *self, gint index);
void sl_attribute_set_all (SlAttribute *self, GList *values);
GList *sl_attribute_get_all (SlAttribute *self);
void sl_attribute_remove_all (SlAttribute *self);
+void sl_attribute_modified (SlAttribute *self);
+gboolean sl_attribute_modified_at (SlAttribute *self, gint index);
-gint sl_attribute_get_value_count (SlAttribute *self);
+void sl_attribute_add_emit (SlAttribute *self, gpointer value, gboolean emit);
+gboolean sl_attribute_set_at_emit (SlAttribute *self, gint index, gpointer value, gboolean emit);
+gboolean sl_attribute_remove_at_emit (SlAttribute *self, gint index, gboolean emit);
+void sl_attribute_remove_all_emit (SlAttribute *self, gboolean emit);
+gboolean sl_attribute_modified_at_emit (SlAttribute *self, gint index, gboolean emit);
-const gchar *sl_attribute_get_name (SlAttribute *self);
+void sl_attribute_emit_modified (SlAttribute *self);
+
+/* internal getters & setters */
+SlEntity *sl_attribute_get_entity (SlAttribute *self);
+void sl_attribute_set_entity (SlAttribute *self, SlEntity *entity);
+GList *sl_attribute_get_eattributes (SlAttribute *self);
+
+/* eattributes */
+void sl_attribute_update_eattributes (SlAttribute *self, GList *eattributes);
+void sl_attribute_add_from_eattr (SlAttribute *self, EVCardAttribute *eattr);
+void sl_attribute_set_all_from_eattributes (SlAttribute *self, GList *eattributes);
+
+EVCardAttribute *sl_attribute_create_eattr (SlAttribute *self, gpointer value);
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]