gtksourceview r2014 - in trunk: . docs/reference gtksourceview tests
- From: pborelli svn gnome org
- To: svn-commits-list gnome org
- Subject: gtksourceview r2014 - in trunk: . docs/reference gtksourceview tests
- Date: Sat, 9 Aug 2008 10:47:33 +0000 (UTC)
Author: pborelli
Date: Sat Aug 9 10:47:33 2008
New Revision: 2014
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2014&view=rev
Log:
2008-08-09 Paolo Borelli <paolo borelli katamail com>
New API: gtk_source_view_[set|get]_draw_spaces, bug #441513.
* gtksourceview/gtksourceview.h:
* gtksourceview/gtksourceview.c:
Allow to draw spaces, tabs and newlines
* gtksourceview/gtksourcestylescheme.h:
* gtksourceview/gtksourcestylescheme.c:
Get the color for drawing spaces
* tests/test-widget.c: use the new feature.
Modified:
trunk/ChangeLog
trunk/docs/reference/gtksourceview-2.0-sections.txt
trunk/gtksourceview/gtksourcestylescheme.c
trunk/gtksourceview/gtksourcestylescheme.h
trunk/gtksourceview/gtksourceview.c
trunk/gtksourceview/gtksourceview.h
trunk/tests/test-widget.c
Modified: trunk/docs/reference/gtksourceview-2.0-sections.txt
==============================================================================
--- trunk/docs/reference/gtksourceview-2.0-sections.txt (original)
+++ trunk/docs/reference/gtksourceview-2.0-sections.txt Sat Aug 9 10:47:33 2008
@@ -47,6 +47,7 @@
GtkSourceView
GtkSourceViewClass
GtkSourceSmartHomeEndType
+GtkSourceDrawSpacesFlags
gtk_source_view_new
gtk_source_view_new_with_buffer
gtk_source_view_set_auto_indent
@@ -77,6 +78,8 @@
gtk_source_view_get_right_margin_position
gtk_source_view_set_tab_width
gtk_source_view_get_tab_width
+gtk_source_view_set_draw_spaces
+gtk_source_view_get_draw_spaces
<SUBSECTION Standard>
GTK_IS_SOURCE_VIEW
GTK_IS_SOURCE_VIEW_CLASS
Modified: trunk/gtksourceview/gtksourcestylescheme.c
==============================================================================
--- trunk/gtksourceview/gtksourcestylescheme.c (original)
+++ trunk/gtksourceview/gtksourcestylescheme.c Sat Aug 9 10:47:33 2008
@@ -36,6 +36,7 @@
#define STYLE_CURRENT_LINE "current-line"
#define STYLE_LINE_NUMBERS "line-numbers"
#define STYLE_RIGHT_MARGIN "right-margin"
+#define STYLE_DRAW_SPACES "draw-spaces"
#define STYLE_SCHEME_VERSION "1.0"
@@ -246,6 +247,7 @@
{
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
g_return_val_if_fail (scheme->priv->id != NULL, "");
+
return scheme->priv->id;
}
@@ -262,6 +264,7 @@
{
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
g_return_val_if_fail (scheme->priv->name != NULL, "");
+
return scheme->priv->name;
}
@@ -277,6 +280,7 @@
gtk_source_style_scheme_get_description (GtkSourceStyleScheme *scheme)
{
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
+
return scheme->priv->description;
}
@@ -314,6 +318,7 @@
gtk_source_style_scheme_get_filename (GtkSourceStyleScheme *scheme)
{
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
+
return scheme->priv->filename;
}
@@ -509,6 +514,7 @@
_gtk_source_style_scheme_get_matching_brackets_style (GtkSourceStyleScheme *scheme)
{
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
+
return gtk_source_style_scheme_get_style (scheme, STYLE_BRACKET_MATCH);
}
@@ -516,9 +522,18 @@
_gtk_source_style_scheme_get_right_margin_style (GtkSourceStyleScheme *scheme)
{
g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
+
return gtk_source_style_scheme_get_style (scheme, STYLE_RIGHT_MARGIN);
}
+GtkSourceStyle *
+_gtk_source_style_scheme_get_draw_spaces_style (GtkSourceStyleScheme *scheme)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_STYLE_SCHEME (scheme), NULL);
+
+ return gtk_source_style_scheme_get_style (scheme, STYLE_DRAW_SPACES);
+}
+
static gboolean
get_color (GtkSourceStyle *style,
gboolean foreground,
Modified: trunk/gtksourceview/gtksourcestylescheme.h
==============================================================================
--- trunk/gtksourceview/gtksourcestylescheme.h (original)
+++ trunk/gtksourceview/gtksourcestylescheme.h Sat Aug 9 10:47:33 2008
@@ -81,6 +81,8 @@
(GtkSourceStyleScheme *scheme);
GtkSourceStyle *_gtk_source_style_scheme_get_right_margin_style
(GtkSourceStyleScheme *scheme);
+GtkSourceStyle *_gtk_source_style_scheme_get_draw_spaces_style
+ (GtkSourceStyleScheme *scheme);
gboolean _gtk_source_style_scheme_get_current_line_color
(GtkSourceStyleScheme *scheme,
GdkColor *color);
Modified: trunk/gtksourceview/gtksourceview.c
==============================================================================
--- trunk/gtksourceview/gtksourceview.c (original)
+++ trunk/gtksourceview/gtksourceview.c Sat Aug 9 10:47:33 2008
@@ -95,7 +95,8 @@
PROP_RIGHT_MARGIN_POSITION,
PROP_SMART_HOME_END,
PROP_HIGHLIGHT_CURRENT_LINE,
- PROP_INDENT_ON_TAB
+ PROP_INDENT_ON_TAB,
+ PROP_DRAW_SPACES
};
struct _GtkSourceViewPrivate
@@ -120,6 +121,9 @@
GdkColor *right_margin_line_color;
GdkColor *right_margin_overlay_color;
+ GtkSourceDrawSpacesFlags draw_spaces;
+ GdkColor *spaces_color;
+
GHashTable *mark_categories;
GtkSourceBuffer *source_buffer;
@@ -383,6 +387,22 @@
TRUE,
G_PARAM_READWRITE));
+ /**
+ * GtkSourceView:draw-spaces:
+ *
+ * Set if and how the spaces should be visualized.
+ *
+ * Since: 2.4
+ */
+ g_object_class_install_property (object_class,
+ PROP_DRAW_SPACES,
+ g_param_spec_flags ("draw-spaces",
+ _("Draw Spaces"),
+ _("Set if and how the spaces should be visualized"),
+ GTK_TYPE_SOURCE_DRAW_SPACES_FLAGS,
+ 0,
+ G_PARAM_READWRITE));
+
signals [UNDO] =
g_signal_new ("undo",
G_TYPE_FROM_CLASS (klass),
@@ -576,6 +596,11 @@
g_value_get_boolean (value));
break;
+ case PROP_DRAW_SPACES:
+ gtk_source_view_set_draw_spaces (view,
+ g_value_get_flags (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -637,8 +662,8 @@
break;
case PROP_SMART_HOME_END:
- g_value_set_flags (value,
- gtk_source_view_get_smart_home_end (view));
+ g_value_set_enum (value,
+ gtk_source_view_get_smart_home_end (view));
break;
case PROP_HIGHLIGHT_CURRENT_LINE:
@@ -651,6 +676,11 @@
gtk_source_view_get_indent_on_tab (view));
break;
+ case PROP_DRAW_SPACES:
+ g_value_set_flags (value,
+ gtk_source_view_get_draw_spaces (view));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -687,6 +717,7 @@
view->priv->right_margin_line_color = NULL;
view->priv->right_margin_overlay_color = NULL;
+ view->priv->spaces_color = NULL;
view->priv->mark_categories = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
@@ -744,6 +775,9 @@
if (view->priv->right_margin_overlay_color != NULL)
gdk_color_free (view->priv->right_margin_overlay_color);
+
+ if (view->priv->spaces_color != NULL)
+ gdk_color_free (view->priv->spaces_color);
if (view->priv->mark_categories)
g_hash_table_destroy (view->priv->mark_categories);
@@ -1528,7 +1562,7 @@
line_rect.x += MAX (0, margin - 1);
cr = gdk_cairo_create (event->window);
- gdk_cairo_set_source_color (cr, color);
+ gdk_cairo_set_source_color (cr, (GdkColor *)color);
cairo_set_line_width (cr, 1);
cairo_rectangle (cr, line_rect.x + .5, line_rect.y + .5,
line_rect.width - 1, line_rect.height - 1);
@@ -1649,6 +1683,211 @@
g_array_free (numbers, TRUE);
}
+static void
+draw_space_at_iter (cairo_t *cr,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ GdkRectangle rect)
+{
+ gint x, y;
+
+ gtk_text_view_buffer_to_window_coords (view,
+ GTK_TEXT_WINDOW_TEXT,
+ rect.x + rect.width / 2,
+ rect.y + rect.height * 2 / 3,
+ &x,
+ &y);
+
+ cairo_save (cr);
+ cairo_move_to (cr, x, y);
+ cairo_arc (cr, x, y, 0.8, 0, 2 * G_PI);
+ cairo_restore (cr);
+}
+
+static void
+draw_tab_at_iter (cairo_t *cr,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ GdkRectangle rect)
+{
+ gint x, y;
+ double w, h;
+
+ gtk_text_view_buffer_to_window_coords (view,
+ GTK_TEXT_WINDOW_TEXT,
+ rect.x,
+ rect.y + rect.height * 2 / 3,
+ &x,
+ &y);
+
+ w = rect.width;
+ h = rect.height;
+
+ cairo_save (cr);
+ cairo_move_to (cr, x + w * 1 / 8, y);
+ cairo_rel_line_to (cr, w * 6 / 8, 0);
+ cairo_rel_line_to (cr, -h * 1 / 4, -h * 1 / 4);
+ cairo_rel_move_to (cr, +h * 1 / 4, +h * 1 / 4);
+ cairo_rel_line_to (cr, -h * 1 / 4, +h * 1 / 4);
+ cairo_restore (cr);
+}
+
+static void
+draw_newline_at_iter (cairo_t *cr,
+ GtkTextView *view,
+ GtkTextIter *iter,
+ GdkRectangle rect)
+{
+ gint x, y;
+ double w, h;
+
+ gtk_text_view_buffer_to_window_coords (view,
+ GTK_TEXT_WINDOW_TEXT,
+ rect.x,
+ rect.y + rect.height * 1 / 3,
+ &x,
+ &y);
+
+ /* width for new line is 0, we use 2 * h */
+ w = 2 * rect.height;
+ h = rect.height;
+
+ cairo_save (cr);
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_LTR)
+ {
+ cairo_move_to (cr, x + w * 7 / 8, y);
+ cairo_rel_line_to (cr, 0, h * 1 / 3);
+ cairo_rel_line_to (cr, -w * 6 / 8, 0);
+ cairo_rel_line_to (cr, +h * 1 / 4, -h * 1 / 4);
+ cairo_rel_move_to (cr, -h * 1 / 4, +h * 1 / 4);
+ cairo_rel_line_to (cr, +h * 1 / 4, +h * 1 / 4);
+ }
+ else
+ {
+ cairo_move_to (cr, x + w * 1 / 8, y);
+ cairo_rel_line_to (cr, 0, h * 1 / 3);
+ cairo_rel_line_to (cr, w * 6 / 8, 0);
+ cairo_rel_line_to (cr, -h * 1 / 4, -h * 1 / 4);
+ cairo_rel_move_to (cr, +h * 1 / 4, +h * 1 / 4);
+ cairo_rel_line_to (cr, -h * 1 / 4, -h * 1 / 4);
+ }
+
+ cairo_restore (cr);
+}
+
+static void
+draw_spaces_at_iter (cairo_t *cr,
+ GtkSourceView *view,
+ GtkTextIter *iter,
+ GdkRectangle rect)
+{
+ gunichar c;
+
+ c = gtk_text_iter_get_char (iter);
+
+ if (view->priv->draw_spaces & GTK_SOURCE_DRAW_SPACES_TAB &&
+ c == '\t')
+ {
+ draw_tab_at_iter (cr, GTK_TEXT_VIEW (view), iter, rect);
+ }
+ else if (view->priv->draw_spaces & GTK_SOURCE_DRAW_SPACES_SPACE &&
+ g_unichar_type (c) == G_UNICODE_SPACE_SEPARATOR)
+ {
+ draw_space_at_iter (cr, GTK_TEXT_VIEW (view), iter, rect);
+ }
+ else if (view->priv->draw_spaces & GTK_SOURCE_DRAW_SPACES_NEWLINE &&
+ gtk_text_iter_ends_line (iter))
+ {
+ draw_newline_at_iter (cr, GTK_TEXT_VIEW (view), iter, rect);
+ }
+}
+
+static void
+draw_tabs_and_spaces (GtkSourceView *view,
+ GdkEventExpose *event)
+{
+ GtkTextView *text_view;
+ gint x1, y1, x2, y2;
+ GtkTextIter s, e;
+ cairo_t *cr;
+
+ text_view = GTK_TEXT_VIEW (view);
+
+ x1 = event->area.x;
+ y1 = event->area.y;
+ x2 = x1 + event->area.width;
+ y2 = y1 + event->area.height;
+
+ gtk_text_view_window_to_buffer_coords (text_view,
+ GTK_TEXT_WINDOW_TEXT,
+ x1,
+ y1,
+ &x1,
+ &y1);
+
+ gtk_text_view_window_to_buffer_coords (text_view,
+ GTK_TEXT_WINDOW_TEXT,
+ x2,
+ y2,
+ &x2,
+ &y2);
+
+ gtk_text_view_get_iter_at_location (text_view,
+ &s,
+ x1, y1);
+ gtk_text_view_get_iter_at_location (text_view,
+ &e,
+ x2, y2);
+
+ cr = gdk_cairo_create (event->window);
+
+ cairo_set_source_rgba (cr,
+ view->priv->spaces_color->red / 65535.,
+ view->priv->spaces_color->green / 65535.,
+ view->priv->spaces_color->blue / 65535.,
+ 1);
+ cairo_set_line_width (cr, 0.8);
+
+ do {
+ GdkRectangle rect;
+ gint ly;
+
+ gtk_text_view_get_iter_location (text_view, &s, &rect);
+
+ /* just iterate on the text that is in the exposed area */
+ if (rect.x > x2)
+ {
+ if (!gtk_text_iter_forward_line (&s))
+ break;
+
+ /* move to the first iter in the exposed area of
+ * the next line */
+ gtk_text_view_get_line_yrange (text_view, &s, &ly, NULL);
+
+ gtk_text_view_get_iter_at_location (text_view,
+ &s,
+ x1, ly);
+
+ /* move back one char otherwise tabs may not
+ * be redrawn */
+ if (!gtk_text_iter_starts_line (&s))
+ gtk_text_iter_backward_char (&s);
+
+ continue;
+ }
+
+ draw_spaces_at_iter (cr, view, &s, rect);
+
+ if (!gtk_text_iter_forward_char (&s))
+ break;
+
+ } while (gtk_text_iter_compare (&s, &e) <= 0);
+
+ cairo_stroke (cr);
+
+ cairo_destroy (cr);
+}
+
static gint
gtk_source_view_expose (GtkWidget *widget,
GdkEventExpose *event)
@@ -1844,6 +2083,12 @@
g_timer_elapsed (timer, NULL) * 1000);
});
}
+
+ if (view->priv->draw_spaces != 0 &&
+ (event->window == gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT)))
+ {
+ draw_tabs_and_spaces (view, event);
+ }
}
DEBUG ({
@@ -3456,6 +3701,48 @@
}
/**
+ * gtk_source_view_set_draw_spaces:
+ * @view: a #GtkSourceView.
+ * @flags: #GtkSourceDrawSpacesFlags specifing how white spaces should
+ * be displayed
+ *
+ * Set if and how the spaces should be visualized. Specifying @flags as 0 will
+ * disable display of spaces.
+ **/
+void
+gtk_source_view_set_draw_spaces (GtkSourceView *view,
+ GtkSourceDrawSpacesFlags flags)
+{
+ g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
+
+ if (view->priv->draw_spaces == flags)
+ return;
+
+ view->priv->draw_spaces = flags;
+
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+
+ g_object_notify (G_OBJECT (view), "draw-spaces");
+}
+
+/**
+ * gtk_source_view_get_draw_spaces:
+ * @view: a #GtkSourceView
+ *
+ * Returns the #GtkSourceDrawSpacesFlags specifying if and how spaces
+ * should be displayed for this @view.
+ *
+ * Returns: the #GtkSourceDrawSpacesFlags, 0 if no spaces should be drawn.
+ **/
+GtkSourceDrawSpacesFlags
+gtk_source_view_get_draw_spaces (GtkSourceView *view)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), 0);
+
+ return view->priv->draw_spaces;
+}
+
+/**
* gtk_source_view_style_set:
* @widget: a #GtkSourceView.
* @previous_style:
@@ -3562,6 +3849,48 @@
}
static void
+update_spaces_color (GtkSourceView *view)
+{
+ GtkWidget *widget = GTK_WIDGET (view);
+
+ if (!GTK_WIDGET_REALIZED (view))
+ return;
+
+ if (view->priv->spaces_color != NULL)
+ {
+ gdk_color_free (view->priv->spaces_color);
+ view->priv->spaces_color = NULL;
+ }
+
+ if (view->priv->style_scheme)
+ {
+ GtkSourceStyle *style;
+
+ style = _gtk_source_style_scheme_get_draw_spaces_style (view->priv->style_scheme);
+
+ if (style != NULL)
+ {
+ gchar *color_str = NULL;
+ GdkColor color;
+
+ g_object_get (style,
+ "foreground", &color_str,
+ NULL);
+
+ if (color_str != NULL && gdk_color_parse (color_str, &color))
+ {
+ view->priv->spaces_color = gdk_color_copy (&color);
+ }
+
+ g_free (color_str);
+ }
+ }
+
+ if (view->priv->spaces_color == NULL)
+ view->priv->spaces_color = gdk_color_copy (&widget->style->text[GTK_STATE_INSENSITIVE]);
+}
+
+static void
gtk_source_view_realize (GtkWidget *widget)
{
GtkSourceView *view = GTK_SOURCE_VIEW (widget);
@@ -3576,6 +3905,7 @@
update_current_line_color (view);
update_right_margin_colors (view);
+ update_spaces_color (view);
}
static void
@@ -3604,6 +3934,7 @@
_gtk_source_style_scheme_apply (new_scheme, GTK_WIDGET (view));
update_current_line_color (view);
update_right_margin_colors (view);
+ update_spaces_color (view);
view->priv->style_scheme_applied = TRUE;
}
else
Modified: trunk/gtksourceview/gtksourceview.h
==============================================================================
--- trunk/gtksourceview/gtksourceview.h (original)
+++ trunk/gtksourceview/gtksourceview.h Sat Aug 9 10:47:33 2008
@@ -85,6 +85,29 @@
GTK_SOURCE_SMART_HOME_END_ALWAYS
} GtkSourceSmartHomeEndType;
+/**
+ * GtkSourceDrawSpacesFlags:
+ * @GTK_SOURCE_DRAW_SPACES_SPACE: whether the space character should be drawn.
+ * @GTK_SOURCE_DRAW_SPACES_TAB: whether the tab character should be drawn.
+ * @GTK_SOURCE_DRAW_SPACES_NEWLINE: whether the line breaks should be drawn.
+ * @GTK_SOURCE_DRAW_SPACES_ALL: wheter all kind of spaces should be drawn.
+ *
+ * GtkSourceDrawSpacesFlags determine what kind of spaces whould be drawn.
+ */
+typedef enum
+{
+ GTK_SOURCE_DRAW_SPACES_SPACE = 1 << 0,
+ GTK_SOURCE_DRAW_SPACES_TAB = 1 << 1,
+ GTK_SOURCE_DRAW_SPACES_NEWLINE = 1 << 2,
+ GTK_SOURCE_DRAW_SPACES_ALL = (GTK_SOURCE_DRAW_SPACES_SPACE | \
+ GTK_SOURCE_DRAW_SPACES_TAB | \
+ GTK_SOURCE_DRAW_SPACES_NEWLINE)
+
+ /* TODO: it would be nice to have flags to specify to draw
+ * just leading/trailing whitespaces */
+} GtkSourceDrawSpacesFlags;
+
+
GType gtk_source_view_get_type (void) G_GNUC_CONST;
/* Constructors */
@@ -168,5 +191,10 @@
GtkSourceSmartHomeEndType
gtk_source_view_get_smart_home_end (GtkSourceView *view);
+void gtk_source_view_set_draw_spaces (GtkSourceView *view,
+ GtkSourceDrawSpacesFlags flags);
+GtkSourceDrawSpacesFlags
+ gtk_source_view_get_draw_spaces (GtkSourceView *view);
+
G_END_DECLS
#endif /* end of SOURCE_VIEW_H__ */
Modified: trunk/tests/test-widget.c
==============================================================================
--- trunk/tests/test-widget.c (original)
+++ trunk/tests/test-widget.c Sat Aug 9 10:47:33 2008
@@ -74,6 +74,8 @@
gpointer user_data);
static void hl_line_toggled_cb (GtkAction *action,
gpointer user_data);
+static void draw_spaces_toggled_cb (GtkAction *action,
+ gpointer user_data);
static void wrap_lines_toggled_cb (GtkAction *action,
gpointer user_data);
static void auto_indent_toggled_cb (GtkAction *action,
@@ -130,6 +132,9 @@
{ "HlLine", NULL, "_Highlight Current Line", NULL,
"Toggle highlighting of current line",
G_CALLBACK (hl_line_toggled_cb), FALSE },
+ { "DrawSpaces", NULL, "_Draw Spaces", NULL,
+ "Draw Spaces",
+ G_CALLBACK (draw_spaces_toggled_cb), FALSE },
{ "WrapLines", NULL, "_Wrap Lines", NULL,
"Toggle line wrapping",
G_CALLBACK (wrap_lines_toggled_cb), FALSE },
@@ -185,6 +190,7 @@
" <menuitem action=\"ShowMarks\"/>"
" <menuitem action=\"ShowMargin\"/>"
" <menuitem action=\"HlLine\"/>"
+" <menuitem action=\"DrawSpaces\"/>"
" <menuitem action=\"WrapLines\"/>"
" <separator/>"
" <menuitem action=\"AutoIndent\"/>"
@@ -513,6 +519,22 @@
}
static void
+draw_spaces_toggled_cb (GtkAction *action, gpointer user_data)
+{
+ gboolean draw_spaces;
+
+ g_return_if_fail (GTK_IS_TOGGLE_ACTION (action) && GTK_IS_SOURCE_VIEW (user_data));
+ draw_spaces = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ if (draw_spaces)
+ gtk_source_view_set_draw_spaces (GTK_SOURCE_VIEW (user_data),
+ GTK_SOURCE_DRAW_SPACES_ALL);
+ else
+ gtk_source_view_set_draw_spaces (GTK_SOURCE_VIEW (user_data),
+ 0);
+}
+
+static void
wrap_lines_toggled_cb (GtkAction *action, gpointer user_data)
{
g_return_if_fail (GTK_IS_TOGGLE_ACTION (action) && GTK_IS_SOURCE_VIEW (user_data));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]