[folks/perf2: 1/2] wip
- From: Niels De Graef <nielsdg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks/perf2: 1/2] wip
- Date: Thu, 26 Nov 2020 20:34:49 +0000 (UTC)
commit 6cec0dee5c98fb80ee776f75f153dc30efc05b3d
Author: Niels De Graef <nielsdegraef gmail com>
Date: Sat Oct 17 19:30:59 2020 +0200
wip
backends/eds/lib/edsf-persona-store.vala | 2 +-
folks/abstract-field-details.vala | 6 +-
folks/individual.vala | 134 +++++++++++++++++++------------
folks/name-details.vala | 6 +-
folks/persona.vala | 6 +-
folks/phone-details.vala | 8 +-
folks/postal-address-details.vala | 2 +-
folks/utils.vala | 20 +++++
8 files changed, 118 insertions(+), 66 deletions(-)
---
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 4cac5620..f558a5f2 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -861,7 +861,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
* here because it fails to null-terminate the array. Sigh. */
this._always_writeable_properties = new string[prop_set.size];
uint i = 0;
- foreach (var final_prop in prop_set)
+ foreach (unowned string final_prop in prop_set)
{
this._always_writeable_properties[i++] = final_prop;
}
diff --git a/folks/abstract-field-details.vala b/folks/abstract-field-details.vala
index ed28cd22..1bfa7802 100644
--- a/folks/abstract-field-details.vala
+++ b/folks/abstract-field-details.vala
@@ -292,8 +292,8 @@ public abstract class Folks.AbstractFieldDetails<T> : Object
GLib.return_val_if_fail (left != null, false);
GLib.return_val_if_fail (right != null, false);
- AbstractFieldDetails left_details = (AbstractFieldDetails) left;
- AbstractFieldDetails right_details = (AbstractFieldDetails) right;
+ unowned var left_details = (AbstractFieldDetails) left;
+ unowned var right_details = (AbstractFieldDetails) right;
return left_details.equal (right_details);
}
@@ -446,7 +446,7 @@ public abstract class Folks.AbstractFieldDetails<T> : Object
{
GLib.return_val_if_fail (value != null, 0);
- AbstractFieldDetails details = (AbstractFieldDetails) value;
+ unowned var details = (AbstractFieldDetails) value;
return details.hash ();
}
}
diff --git a/folks/individual.vala b/folks/individual.vala
index bc63dc11..d5daa146 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -178,8 +178,9 @@ public class Folks.Individual : Object,
/* Try to write it to only the writeable Personas which have the
* "avatar" property as writeable. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
unowned var _a = p as AvatarDetails;
if (_a == null)
{
@@ -365,8 +366,9 @@ public class Folks.Individual : Object,
/* Try to write it to only the writeable Personas which have "alias"
* as a writeable property. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
unowned var _a = p as AliasDetails;
if (_a == null)
{
@@ -474,8 +476,9 @@ public class Folks.Individual : Object,
/* Try to write it to only the writeable Personas which have "nickname"
* as a writeable property. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
unowned var _n = p as NameDetails;
if (_n == null)
{
@@ -725,8 +728,9 @@ public class Folks.Individual : Object,
* NOTE: We don't check whether the persona's store is writeable, as we
* want is-favourite status to propagate to all stores, if possible. This
* is one property which is harmless to propagate. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
unowned var _a = p as FavouriteDetails;
if (_a == null)
{
@@ -803,8 +807,9 @@ public class Folks.Individual : Object,
/* Try to write it to only the Personas which have "groups" as a
* writeable property. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
unowned var _g = p as GroupDetails;
if (_g == null)
{
@@ -890,8 +895,9 @@ public class Folks.Individual : Object,
{
uint counter = 0;
/* Iterate over all personas and sum up their IM interaction counts*/
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var my_interaction_details = persona as InteractionDetails;
if (my_interaction_details != null)
{
@@ -914,8 +920,9 @@ public class Folks.Individual : Object,
if (this._last_im_interaction_datetime == null)
{
/* Iterate over all personas and get the latest IM interaction datetime */
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var my_interaction_details = persona as InteractionDetails;
if (my_interaction_details != null &&
my_interaction_details.last_im_interaction_datetime != null)
@@ -942,8 +949,9 @@ public class Folks.Individual : Object,
{
uint counter = 0;
/* Iterate over all personas and sum up their call interaction counts*/
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var my_interaction_details = persona as InteractionDetails;
if (my_interaction_details != null)
{
@@ -966,9 +974,10 @@ public class Folks.Individual : Object,
if (this._last_call_interaction_datetime == null)
{
/* Iterate over all personas and get the latest IM interaction datetime */
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
- var my_interaction_details = persona as InteractionDetails;
+ unowned var persona = this._persona_set[i];
+ unowned var my_interaction_details = persona as InteractionDetails;
if (my_interaction_details != null &&
my_interaction_details.last_call_interaction_datetime != null)
{
@@ -996,8 +1005,9 @@ public class Folks.Individual : Object,
/* Try to get it from the writeable Personas which have "extended-info"
* as a writeable property. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if ("extended-info" in p.writeable_properties)
{
unowned var e = p as ExtendedInfo;
@@ -1027,8 +1037,9 @@ public class Folks.Individual : Object,
/* Try to write it to only the writeable Personas which have "extended-info"
* as a writeable property. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if ("extended-info" in p.writeable_properties)
{
unowned var e = p as ExtendedInfo;
@@ -1077,8 +1088,9 @@ public class Folks.Individual : Object,
PropertyError? persona_error = null;
/* Try to remove it from all writeable Personas. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if ("extended-info" in p.writeable_properties)
{
unowned var e = p as ExtendedInfo;
@@ -1239,8 +1251,9 @@ public class Folks.Individual : Object,
*/
public async void change_group (string group, bool is_member)
{
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (p is GroupDetails)
((GroupDetails) p).change_group.begin (group, is_member);
}
@@ -1459,8 +1472,9 @@ public class Folks.Individual : Object,
/* Build a set of the remaining personas (those which weren't in the
* removed store. */
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
if (persona.store != store)
{
remaining_personas.add (persona);
@@ -1481,8 +1495,9 @@ public class Folks.Individual : Object,
/* Build a set of the remaining personas (those which aren't in the
* set of removed personas). */
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
if (!removed.contains (persona))
{
remaining_personas.add (persona);
@@ -1619,8 +1634,9 @@ public class Folks.Individual : Object,
unowned Persona? candidate_p = null;
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
/* We only care about personas implementing the given interface. */
if (p.get_type ().is_a (interface_type))
{
@@ -1771,8 +1787,9 @@ public class Folks.Individual : Object,
* "groups-changed" on the store (with the set of personas), to allow the
* back-end to optimize it (like Telepathy will for MembersChanged for the
* groups channel list) */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (p is GroupDetails)
{
unowned var persona = (GroupDetails) p;
@@ -1989,8 +2006,9 @@ public class Folks.Individual : Object,
/* Find the primary persona first. The primary persona's values will be
* preferred in every case where they're set. */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (p.store.is_primary_store)
{
primary_persona = p;
@@ -2001,8 +2019,9 @@ public class Folks.Individual : Object,
/* See if any persona has an alias set. */
new_display_name = this._look_up_alias_for_display_name (primary_persona);
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (new_display_name != "")
{
break;
@@ -2017,8 +2036,9 @@ public class Folks.Individual : Object,
new_display_name =
this._look_up_name_details_for_display_name (primary_persona);
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (new_display_name != "")
{
break;
@@ -2035,8 +2055,9 @@ public class Folks.Individual : Object,
new_display_name =
this._look_up_email_address_for_display_name (primary_persona);
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (new_display_name != "")
{
break;
@@ -2053,8 +2074,9 @@ public class Folks.Individual : Object,
new_display_name =
this._look_up_phone_number_for_display_name (primary_persona);
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (new_display_name != "")
{
break;
@@ -2071,13 +2093,14 @@ public class Folks.Individual : Object,
new_display_name =
this._look_up_display_id_for_display_name (primary_persona);
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
if (new_display_name != "")
{
break;
}
+ unowned var p = this._persona_set[i];
new_display_name =
this._look_up_display_id_for_display_name (p);
}
@@ -2089,8 +2112,9 @@ public class Folks.Individual : Object,
new_display_name =
this._look_up_postal_address_for_display_name (primary_persona);
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (new_display_name != "")
{
break;
@@ -2112,7 +2136,7 @@ public class Folks.Individual : Object,
if (new_display_name != this._display_name)
{
- this._display_name = new_display_name;
+ this._display_name = (owned) new_display_name;
debug ("Setting display name ā%sā", new_display_name);
this.notify_property ("display-name");
}
@@ -2125,7 +2149,7 @@ public class Folks.Individual : Object,
unowned var alias = ((AliasDetails) p).alias;
return_val_if_fail (alias != null, false);
- return (alias.strip () != ""); /* empty aliases are unset */
+ return !Utils.is_string_empty (alias); /* empty aliases are unset */
}, (a, b) =>
{
unowned var a_alias = ((AliasDetails) a).alias;
@@ -2134,8 +2158,8 @@ public class Folks.Individual : Object,
return_val_if_fail (a_alias != null, 0);
return_val_if_fail (b_alias != null, 0);
- var a_is_empty = (a_alias.strip () == "") ? 1 : 0;
- var b_is_empty = (b_alias.strip () == "") ? 1 : 0;
+ var a_is_empty = Utils.is_string_empty (a_alias) ? 1 : 0;
+ var b_is_empty = Utils.is_string_empty (b_alias) ? 1 : 0;
/* We prefer to not have an alias which is the same as the Persona's
* display-id, since having such an alias implies that it's the
@@ -2203,8 +2227,9 @@ public class Folks.Individual : Object,
{
var trust_level = TrustLevel.PERSONAS;
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (p.is_user == false &&
p.store.trust_level == PersonaStoreTrust.NONE)
trust_level = TrustLevel.NONE;
@@ -2231,10 +2256,10 @@ public class Folks.Individual : Object,
null, null, AbstractFieldDetails<string>.hash_static,
AbstractFieldDetails<string>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
/* We only care about personas implementing the given interface. */
- unowned var im_details = persona as ImDetails;
+ unowned var im_details = this._persona_set[i] as ImDetails;
if (im_details != null)
{
var iter = im_details.im_addresses.map_iterator ();
@@ -2275,8 +2300,9 @@ public class Folks.Individual : Object,
AbstractFieldDetails<string>.hash_static,
AbstractFieldDetails<string>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
/* We only care about personas implementing the given interface. */
unowned var web_service_details = persona as WebServiceDetails;
if (web_service_details != null)
@@ -2368,7 +2394,7 @@ public class Folks.Individual : Object,
unowned var name = ((NameDetails) p).full_name;
return_val_if_fail (name != null, false);
- return (name.strip () != ""); /* empty names are unset */
+ return !Utils.is_string_empty (name); /* empty names are unset */
}, (a, b) =>
{
/* Can't compare two set names. */
@@ -2384,7 +2410,7 @@ public class Folks.Individual : Object,
if (new_full_name != this._full_name)
{
- this._full_name = new_full_name;
+ this._full_name = (owned) new_full_name;
this.notify_property ("full-name");
this._update_display_name ();
@@ -2399,7 +2425,7 @@ public class Folks.Individual : Object,
unowned var nickname = ((NameDetails) p).nickname;
return_val_if_fail (nickname != null, false);
- return (nickname.strip () != ""); /* empty names are unset */
+ return !Utils.is_string_empty (nickname); /* empty names are unset */
}, (a, b) =>
{
/* Can't compare two set names. */
@@ -2415,7 +2441,7 @@ public class Folks.Individual : Object,
if (new_nickname != this._nickname)
{
- this._nickname = new_nickname;
+ this._nickname = (owned) new_nickname;
this.notify_property ("nickname");
this._update_display_name ();
@@ -2508,12 +2534,12 @@ public class Folks.Individual : Object,
unowned UrlFieldDetails> (
null, null, AbstractFieldDetails<string>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
/* We only care about personas implementing the given
* interface. If the same URL exists multiple times we merge
* the parameters. */
- unowned var url_details = persona as UrlDetails;
+ unowned var url_details = this._persona_set[i] as UrlDetails;
if (url_details != null)
{
foreach (var url_fd in ((!) url_details).urls)
@@ -2565,12 +2591,12 @@ public class Folks.Individual : Object,
var phone_numbers_set = new HashMap<string, PhoneFieldDetails> (
null, null, AbstractFieldDetails<string>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
/* We only care about personas implementing the given
* interface. If the same phone number exists multiple times
* we merge the parameters. */
- unowned var phone_details = persona as PhoneDetails;
+ unowned var phone_details = this._persona_set[i] as PhoneDetails;
if (phone_details != null)
{
foreach (var phone_fd in ((!) phone_details).phone_numbers)
@@ -2622,8 +2648,10 @@ public class Folks.Individual : Object,
var emails_set = new HashMap<string, EmailFieldDetails> (
null, null, AbstractFieldDetails<string>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
+
/* We only care about personas implementing the given
* interface. If the same e-mail address exists multiple times
* we merge the parameters. */
@@ -2678,9 +2706,9 @@ public class Folks.Individual : Object,
AbstractFieldDetails<Role>.hash_static,
AbstractFieldDetails<Role>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
- var role_details = persona as RoleDetails;
+ unowned var role_details = this._persona_set[i] as RoleDetails;
if (role_details != null)
{
foreach (var role_fd in ((!) role_details).roles)
@@ -2714,8 +2742,9 @@ public class Folks.Individual : Object,
{
var new_local_ids = new SmallSet<string> ();
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var local_id_details = persona as LocalIdDetails;
if (local_id_details != null)
{
@@ -2784,8 +2813,9 @@ public class Folks.Individual : Object,
AbstractFieldDetails<PostalAddress>.hash_static,
AbstractFieldDetails<PostalAddress>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var postal_address_details = persona as PostalAddressDetails;
if (postal_address_details != null)
{
@@ -2879,8 +2909,9 @@ public class Folks.Individual : Object,
AbstractFieldDetails<string>.hash_static,
AbstractFieldDetails<string>.equal_static);
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var note_details = persona as NoteDetails;
if (note_details != null)
{
@@ -2947,8 +2978,9 @@ public class Folks.Individual : Object,
}
/* Determine which Personas have been removed */
- foreach (var p in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var p = this._persona_set[i];
if (personas == null || !((!) personas).contains (p))
{
/* Keep track of how many Personas are users */
@@ -3022,8 +3054,9 @@ public class Folks.Individual : Object,
{
unowned Persona? chosen_persona = null;
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
if (chosen_persona == null)
{
chosen_persona = persona;
@@ -3096,8 +3129,9 @@ public class Folks.Individual : Object,
{
unowned var al = p as AntiLinkable;
- foreach (var persona in this._persona_set)
+ for (int i = 0; i < this._persona_set.size; i++)
{
+ unowned var persona = this._persona_set[i];
unowned var pl = persona as AntiLinkable;
if ((al != null && ((!) al).has_anti_link_with_persona (persona)) ||
diff --git a/folks/name-details.vala b/folks/name-details.vala
index d5fb1415..ee72e7d2 100644
--- a/folks/name-details.vala
+++ b/folks/name-details.vala
@@ -214,7 +214,7 @@ public class Folks.StructuredName : Object
}
}
- return output.str;
+ return (owned) output.str;
}
/**
@@ -265,7 +265,7 @@ public class Folks.StructuredName : Object
* punctuation, please file a bug against libfolks:
* https://gitlab.gnome.org/GNOME/folks/issues
*/
- var name_fmt = _("%g%t%m%t%f");
+ unowned var name_fmt = _("%g%t%m%t%f");
return this.to_string_with_format (name_fmt);
}
@@ -372,7 +372,7 @@ public class Folks.StructuredName : Object
}
}
- return output.str;
+ return (owned) output.str;
}
}
diff --git a/folks/persona.vala b/folks/persona.vala
index ecbadb9f..add9be12 100644
--- a/folks/persona.vala
+++ b/folks/persona.vala
@@ -283,7 +283,7 @@ public abstract class Folks.Persona : Object
assert_not_reached ();
}
- private static string _add_escaped_uid_component (StringBuilder uid, string component)
+ private static void _add_escaped_uid_component (StringBuilder uid, string component)
{
/* Escape colons with backslashes */
for (int i = 0; i < component.length; i++)
@@ -295,8 +295,6 @@ public abstract class Folks.Persona : Object
}
uid.append_c (c);
}
-
- return uid.str;
}
private static string _unescape_uid_component (string component)
@@ -338,7 +336,7 @@ public abstract class Folks.Persona : Object
uid.append_c (':');
Persona._add_escaped_uid_component (uid, persona_id);
- return uid.str;
+ return (owned) uid.str;
}
/**
diff --git a/folks/phone-details.vala b/folks/phone-details.vala
index 141ac073..9e97eb3b 100644
--- a/folks/phone-details.vala
+++ b/folks/phone-details.vala
@@ -91,10 +91,10 @@ public class Folks.PhoneFieldDetails : AbstractFieldDetails<string>
*/
public override bool values_equal (AbstractFieldDetails<string> that)
{
- var _that_fd = that as PhoneFieldDetails;
+ unowned var _that_fd = that as PhoneFieldDetails;
if (_that_fd == null)
return false;
- PhoneFieldDetails that_fd = (!) _that_fd;
+ unowned PhoneFieldDetails that_fd = (!) _that_fd;
var n1 = PhoneFieldDetails._drop_extension (this.get_normalised ());
var n2 = PhoneFieldDetails._drop_extension (that_fd.get_normalised ());
@@ -185,7 +185,7 @@ public class Folks.PhoneFieldDetails : AbstractFieldDetails<string>
builder.append_c (digit);
}
- return builder.str;
+ return (owned) builder.str;
}
/**
@@ -214,7 +214,7 @@ public class Folks.PhoneFieldDetails : AbstractFieldDetails<string>
builder.append_c (digit);
}
- return builder.str;
+ return (owned) builder.str;
}
}
diff --git a/folks/postal-address-details.vala b/folks/postal-address-details.vala
index f08d874e..d40bd1a7 100644
--- a/folks/postal-address-details.vala
+++ b/folks/postal-address-details.vala
@@ -229,7 +229,7 @@ public class Folks.PostalAddress : Object
*/
public string to_string ()
{
- var str = _("%s, %s, %s, %s, %s, %s, %s");
+ unowned var str = _("%s, %s, %s, %s, %s, %s, %s");
return str.printf (this.po_box, this.extension, this.street,
this.locality, this.region, this.postal_code, this.country);
}
diff --git a/folks/utils.vala b/folks/utils.vala
index 2339e273..a69086a9 100644
--- a/folks/utils.vala
+++ b/folks/utils.vala
@@ -273,4 +273,24 @@ public class Folks.Utils : Object
return true;
}
+
+ /**
+ * Checks whether the given string is empty, ignoring any trailing or leading
+ * whitespace. Basically, it's the same as executing (str.strip() != ""), but
+ * without unnecessarily creating a string copy.
+ *
+ * @param str The string to check for
+ * @since 0.14.1
+ */
+ public static bool is_string_empty (string str)
+ {
+ int length = str.length;
+ for (int i = 0; i < length; i++)
+ {
+ if (! str[i].isspace ())
+ return false;
+ }
+
+ return true;
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]