[gtk+/wip/cssvalue: 4/141] css: Add GtkCssMatcher
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/cssvalue: 4/141] css: Add GtkCssMatcher
- Date: Sat, 7 Apr 2012 17:46:29 +0000 (UTC)
commit 7b31f227df435ee240fd9b9b67d60363cf66b31f
Author: Benjamin Otte <otte redhat com>
Date: Sat Mar 17 02:17:23 2012 +0100
css: Add GtkCssMatcher
This is so we can later do matching with other things than
GtkWidgetPath.
In particular, this is a requirement for getting rid of GtkWidgetPath.
gtk/Makefile.am | 2 +
gtk/gtkcssmatcher.c | 174 ++++++++++++++++++++++++++++++++++++++++
gtk/gtkcssmatcherprivate.h | 61 ++++++++++++++
gtk/gtkcssselector.c | 188 +++++++++++++++-----------------------------
4 files changed, 301 insertions(+), 124 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index e062c9a..7559239 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -431,6 +431,7 @@ gtk_private_h_sources = \
gtkcssimageurlprivate.h \
gtkcssimagewin32private.h \
gtkcsslookupprivate.h \
+ gtkcssmatcherprivate.h \
gtkcssparserprivate.h \
gtkcssproviderprivate.h \
gtkcsssectionprivate.h \
@@ -627,6 +628,7 @@ gtk_base_c_sources = \
gtkcssimageurl.c \
gtkcssimagewin32.c \
gtkcsslookup.c \
+ gtkcssmatcher.c \
gtkcssparser.c \
gtkcssprovider.c \
gtkcsssection.c \
diff --git a/gtk/gtkcssmatcher.c b/gtk/gtkcssmatcher.c
new file mode 100644
index 0000000..583b803
--- /dev/null
+++ b/gtk/gtkcssmatcher.c
@@ -0,0 +1,174 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2012 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcssmatcherprivate.h"
+
+#include "gtkwidgetpath.h"
+
+void
+_gtk_css_matcher_init (GtkCssMatcher *matcher,
+ const GtkWidgetPath *path,
+ GtkStateFlags state)
+{
+ matcher->path = path;
+ matcher->state_flags = state;
+ matcher->index = gtk_widget_path_length (path) - 1;
+ matcher->sibling_index = gtk_widget_path_iter_get_sibling_index (path, matcher->index);
+}
+
+gboolean
+_gtk_css_matcher_get_parent (GtkCssMatcher *matcher,
+ const GtkCssMatcher *child)
+{
+ if (child->index == 0)
+ return FALSE;
+
+ matcher->path = child->path;
+ matcher->state_flags = 0;
+ matcher->index = child->index - 1;
+ matcher->sibling_index = gtk_widget_path_iter_get_sibling_index (matcher->path, matcher->index);
+
+ return TRUE;
+}
+
+gboolean
+_gtk_css_matcher_get_previous (GtkCssMatcher *matcher,
+ const GtkCssMatcher *next)
+{
+ if (next->sibling_index == 0)
+ return FALSE;
+
+ matcher->path = next->path;
+ matcher->state_flags = 0;
+ matcher->index = next->index;
+ matcher->sibling_index = next->sibling_index - 1;
+
+ return TRUE;
+}
+
+gboolean
+_gtk_css_matcher_has_state (const GtkCssMatcher *matcher,
+ GtkStateFlags state_flags)
+{
+ return (matcher->state_flags & state_flags) == state_flags;
+}
+
+gboolean
+_gtk_css_matcher_has_name (const GtkCssMatcher *matcher,
+ const char *name)
+{
+ const GtkWidgetPath *siblings;
+ GType type;
+
+ type = g_type_from_name (name);
+ siblings = gtk_widget_path_iter_get_siblings (matcher->path, matcher->index);
+ if (siblings && matcher->sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path, matcher->index))
+ return g_type_is_a (gtk_widget_path_iter_get_object_type (siblings, matcher->sibling_index), type);
+ else
+ return g_type_is_a (gtk_widget_path_iter_get_object_type (matcher->path, matcher->index), type);
+}
+
+gboolean
+_gtk_css_matcher_has_class (const GtkCssMatcher *matcher,
+ const char *class_name)
+{
+ const GtkWidgetPath *siblings;
+
+ siblings = gtk_widget_path_iter_get_siblings (matcher->path, matcher->index);
+ if (siblings && matcher->sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path, matcher->index))
+ return gtk_widget_path_iter_has_class (siblings, matcher->sibling_index, class_name);
+ else
+ return gtk_widget_path_iter_has_class (matcher->path, matcher->index, class_name);
+}
+
+gboolean
+_gtk_css_matcher_has_id (const GtkCssMatcher *matcher,
+ const char *id)
+{
+ const GtkWidgetPath *siblings;
+
+ siblings = gtk_widget_path_iter_get_siblings (matcher->path, matcher->index);
+ if (siblings && matcher->sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path, matcher->index))
+ return gtk_widget_path_iter_has_name (siblings, matcher->sibling_index, id);
+ else
+ return gtk_widget_path_iter_has_name (matcher->path, matcher->index, id);
+}
+
+gboolean
+_gtk_css_matcher_has_regions (const GtkCssMatcher *matcher)
+{
+ const GtkWidgetPath *siblings;
+ GSList *regions;
+ gboolean result;
+
+ siblings = gtk_widget_path_iter_get_siblings (matcher->path, matcher->index);
+ if (siblings && matcher->sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path, matcher->index))
+ regions = gtk_widget_path_iter_list_regions (siblings, matcher->sibling_index);
+ else
+ regions = gtk_widget_path_iter_list_regions (matcher->path, matcher->index);
+ result = regions != NULL;
+ g_slist_free (regions);
+
+ return result;
+}
+
+gboolean
+_gtk_css_matcher_has_region (const GtkCssMatcher *matcher,
+ const char *region,
+ GtkRegionFlags flags)
+{
+ const GtkWidgetPath *siblings;
+ GtkRegionFlags region_flags;
+
+ siblings = gtk_widget_path_iter_get_siblings (matcher->path, matcher->index);
+ if (siblings && matcher->sibling_index != gtk_widget_path_iter_get_sibling_index (matcher->path, matcher->index))
+ {
+ if (!gtk_widget_path_iter_has_region (siblings, matcher->sibling_index, region, ®ion_flags))
+ return FALSE;
+ }
+ else
+ {
+ if (!gtk_widget_path_iter_has_region (matcher->path, matcher->index, region, ®ion_flags))
+ return FALSE;
+ }
+
+ if ((flags & region_flags) != flags)
+ return FALSE;
+
+ return TRUE;
+}
+
+guint
+_gtk_css_matcher_get_sibling_index (const GtkCssMatcher *matcher)
+{
+ return matcher->sibling_index;
+}
+
+guint
+_gtk_css_matcher_get_n_siblings (const GtkCssMatcher *matcher)
+{
+ const GtkWidgetPath *siblings;
+
+ siblings = gtk_widget_path_iter_get_siblings (matcher->path, matcher->index);
+ if (!siblings)
+ return 0;
+
+ return gtk_widget_path_length (siblings);
+}
+
diff --git a/gtk/gtkcssmatcherprivate.h b/gtk/gtkcssmatcherprivate.h
new file mode 100644
index 0000000..61988a2
--- /dev/null
+++ b/gtk/gtkcssmatcherprivate.h
@@ -0,0 +1,61 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2012 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CSS_MATCHER_PRIVATE_H__
+#define __GTK_CSS_MATCHER_PRIVATE_H__
+
+#include <gtk/gtkenums.h>
+#include <gtk/gtktypes.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkCssMatcher GtkCssMatcher;
+
+struct _GtkCssMatcher {
+ const GtkWidgetPath *path;
+ GtkStateFlags state_flags;
+ guint index;
+ guint sibling_index;
+};
+
+void _gtk_css_matcher_init (GtkCssMatcher *matcher,
+ const GtkWidgetPath *path,
+ GtkStateFlags state);
+gboolean _gtk_css_matcher_get_parent (GtkCssMatcher *matcher,
+ const GtkCssMatcher *child);
+gboolean _gtk_css_matcher_get_previous (GtkCssMatcher *matcher,
+ const GtkCssMatcher *next);
+
+gboolean _gtk_css_matcher_has_state (const GtkCssMatcher *matcher,
+ GtkStateFlags state_flags);
+gboolean _gtk_css_matcher_has_name (const GtkCssMatcher *matcher,
+ const char *name);
+gboolean _gtk_css_matcher_has_class (const GtkCssMatcher *matcher,
+ const char *class_name);
+gboolean _gtk_css_matcher_has_id (const GtkCssMatcher *matcher,
+ const char *id);
+gboolean _gtk_css_matcher_has_regions (const GtkCssMatcher *matcher);
+gboolean _gtk_css_matcher_has_region (const GtkCssMatcher *matcher,
+ const char *region,
+ GtkRegionFlags flags);
+guint _gtk_css_matcher_get_sibling_index
+ (const GtkCssMatcher *matcher);
+guint _gtk_css_matcher_get_n_siblings (const GtkCssMatcher *matcher);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_MATCHER_PRIVATE_H__ */
diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c
index 2f7735d..f526738 100644
--- a/gtk/gtkcssselector.c
+++ b/gtk/gtkcssselector.c
@@ -21,9 +21,9 @@
#include <string.h>
+#include "gtkcssmatcherprivate.h"
#include "gtkcssprovider.h"
#include "gtkstylecontextprivate.h"
-#include "gtkwidgetpath.h"
typedef struct _GtkCssSelectorClass GtkCssSelectorClass;
@@ -33,10 +33,7 @@ struct _GtkCssSelectorClass {
void (* print) (const GtkCssSelector *selector,
GString *string);
gboolean (* match) (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling);
+ const GtkCssMatcher *matcher);
guint increase_id_specificity :1;
guint increase_class_specificity :1;
@@ -53,15 +50,12 @@ struct _GtkCssSelector
static gboolean
gtk_css_selector_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
if (selector == NULL)
return TRUE;
- return selector->class->match (selector, state, path, id, sibling);
+ return selector->class->match (selector, matcher);
}
static const GtkCssSelector *
@@ -83,18 +77,15 @@ gtk_css_selector_descendant_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_descendant_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- while (id-- > 0)
+ GtkCssMatcher descendant;
+
+ while (_gtk_css_matcher_get_parent (&descendant, matcher))
{
- if (gtk_css_selector_match (gtk_css_selector_previous (selector),
- 0,
- path,
- id,
- gtk_widget_path_iter_get_sibling_index (path, id)))
+ matcher = &descendant;
+
+ if (gtk_css_selector_match (gtk_css_selector_previous (selector), matcher))
return TRUE;
}
@@ -119,19 +110,14 @@ gtk_css_selector_child_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_child_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- if (id == 0)
+ GtkCssMatcher parent;
+
+ if (!_gtk_css_matcher_get_parent (&parent, matcher))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector),
- 0,
- path,
- id - 1,
- gtk_widget_path_iter_get_sibling_index (path, id - 1));
+ return gtk_css_selector_match (gtk_css_selector_previous (selector), &parent);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
@@ -152,18 +138,15 @@ gtk_css_selector_sibling_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_sibling_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- while (sibling-- > 0)
+ GtkCssMatcher previous;
+
+ while (_gtk_css_matcher_get_previous (&previous, matcher))
{
- if (gtk_css_selector_match (gtk_css_selector_previous (selector),
- 0,
- path,
- id,
- sibling))
+ matcher = &previous;
+
+ if (gtk_css_selector_match (gtk_css_selector_previous (selector), matcher))
return TRUE;
}
@@ -188,19 +171,14 @@ gtk_css_selector_adjacent_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_adjacent_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- if (sibling == 0)
+ GtkCssMatcher previous;
+
+ if (!_gtk_css_matcher_get_previous (&previous, matcher))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector),
- 0,
- path,
- id,
- sibling - 1);
+ return gtk_css_selector_match (gtk_css_selector_previous (selector), &previous);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
@@ -221,24 +199,19 @@ gtk_css_selector_any_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_any_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
const GtkCssSelector *previous = gtk_css_selector_previous (selector);
- GSList *regions;
if (previous &&
previous->class == >K_CSS_SELECTOR_DESCENDANT &&
- (regions = gtk_widget_path_iter_list_regions (path, id)) != NULL)
+ _gtk_css_matcher_has_regions (matcher))
{
- g_slist_free (regions);
- if (gtk_css_selector_match (gtk_css_selector_previous (previous), state, path, id, sibling))
+ if (gtk_css_selector_match (gtk_css_selector_previous (previous), matcher))
return TRUE;
}
- return gtk_css_selector_match (previous, state, path, id, sibling);
+ return gtk_css_selector_match (previous, matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ANY = {
@@ -259,17 +232,12 @@ gtk_css_selector_name_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_name_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- GType type = g_type_from_name (selector->data);
-
- if (!g_type_is_a (gtk_widget_path_iter_get_object_type (path, id), type))
+ if (!_gtk_css_matcher_has_name (matcher, selector->data))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector), state, path, id, sibling);
+ return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NAME = {
@@ -290,22 +258,19 @@ gtk_css_selector_region_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_region_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
const GtkCssSelector *previous;
- if (!gtk_widget_path_iter_has_region (path, id, selector->data, NULL))
+ if (!_gtk_css_matcher_has_region (matcher, selector->data, 0))
return FALSE;
previous = gtk_css_selector_previous (selector);
if (previous && previous->class == >K_CSS_SELECTOR_DESCENDANT &&
- gtk_css_selector_match (gtk_css_selector_previous (previous), state, path, id, sibling))
+ gtk_css_selector_match (gtk_css_selector_previous (previous), matcher))
return TRUE;
- return gtk_css_selector_match (previous, state, path, id, sibling);
+ return gtk_css_selector_match (previous, matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_REGION = {
@@ -327,15 +292,12 @@ gtk_css_selector_class_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_class_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- if (!gtk_widget_path_iter_has_class (path, id, selector->data))
+ if (!_gtk_css_matcher_has_class (matcher, selector->data))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector), state, path, id, sibling);
+ return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CLASS = {
@@ -357,15 +319,12 @@ gtk_css_selector_id_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_id_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- if (!gtk_widget_path_iter_has_name (path, id, selector->data))
+ if (!_gtk_css_matcher_has_id (matcher, selector->data))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector), state, path, id, sibling);
+ return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ID = {
@@ -409,15 +368,12 @@ gtk_css_selector_pseudoclass_state_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_pseudoclass_state_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- if (!(GPOINTER_TO_UINT (selector->data) & state))
+ if (!_gtk_css_matcher_has_state (matcher, GPOINTER_TO_UINT (selector->data)))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector), state, path, id, sibling);
+ return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_STATE = {
@@ -460,53 +416,43 @@ gtk_css_selector_pseudoclass_region_print (const GtkCssSelector *selector,
static gboolean
gtk_css_selector_pseudoclass_region_match_for_region (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
- GtkRegionFlags selector_flags, path_flags;
+ GtkRegionFlags selector_flags;
const GtkCssSelector *previous;
selector_flags = GPOINTER_TO_UINT (selector->data);
selector = gtk_css_selector_previous (selector);
- if (!gtk_widget_path_iter_has_region (path, id, selector->data, &path_flags))
- return FALSE;
-
- if ((selector_flags & path_flags) != selector_flags)
+ if (!_gtk_css_matcher_has_region (matcher, selector->data, selector_flags))
return FALSE;
previous = gtk_css_selector_previous (selector);
if (previous && previous->class == >K_CSS_SELECTOR_DESCENDANT &&
- gtk_css_selector_match (gtk_css_selector_previous (previous), state, path, id, sibling))
+ gtk_css_selector_match (gtk_css_selector_previous (previous), matcher))
return TRUE;
- return gtk_css_selector_match (previous, state, path, id, sibling);
+ return gtk_css_selector_match (previous, matcher);
}
static gboolean
gtk_css_selector_pseudoclass_region_match (const GtkCssSelector *selector,
- GtkStateFlags state,
- const GtkWidgetPath *path,
- guint id,
- guint sibling)
+ const GtkCssMatcher *matcher)
{
GtkRegionFlags region;
- const GtkWidgetPath *siblings;
- guint n_siblings;
+ guint sibling, n_siblings;
const GtkCssSelector *previous;
previous = gtk_css_selector_previous (selector);
if (previous && previous->class == >K_CSS_SELECTOR_REGION)
- return gtk_css_selector_pseudoclass_region_match_for_region (selector, state, path, id, sibling);
+ return gtk_css_selector_pseudoclass_region_match_for_region (selector, matcher);
- siblings = gtk_widget_path_iter_get_siblings (path, id);
- if (siblings == NULL)
- return 0;
+ n_siblings = _gtk_css_matcher_get_n_siblings (matcher);
+ if (n_siblings == 0)
+ return FALSE;
+ sibling = _gtk_css_matcher_get_sibling_index (matcher);
region = GPOINTER_TO_UINT (selector->data);
- n_siblings = gtk_widget_path_length (siblings);
switch (region)
{
@@ -537,7 +483,7 @@ gtk_css_selector_pseudoclass_region_match (const GtkCssSelector *selector,
return FALSE;
}
- return gtk_css_selector_match (previous, state, path, id, sibling);
+ return gtk_css_selector_match (previous, matcher);
}
static const GtkCssSelectorClass GTK_CSS_SELECTOR_PSEUDOCLASS_REGION = {
@@ -887,20 +833,14 @@ _gtk_css_selector_matches (const GtkCssSelector *selector,
const GtkWidgetPath *path,
GtkStateFlags state)
{
- guint length;
+ GtkCssMatcher matcher;
g_return_val_if_fail (selector != NULL, FALSE);
g_return_val_if_fail (path != NULL, FALSE);
- length = gtk_widget_path_length (path);
- if (length == 0)
- return FALSE;
+ _gtk_css_matcher_init (&matcher, path, state);
- return gtk_css_selector_match (selector,
- state,
- path,
- length - 1,
- gtk_widget_path_iter_get_sibling_index (path, length - 1));
+ return gtk_css_selector_match (selector, &matcher);
}
/* Computes specificity according to CSS 2.1.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]