[vinagre] Second step (in a total of XX) towards plugin support.
- From: Jonh Wendell <jwendell src gnome org>
- To: svn-commits-list gnome org
- Subject: [vinagre] Second step (in a total of XX) towards plugin support.
- Date: Mon, 27 Jul 2009 12:03:07 +0000 (UTC)
commit 2d662641249beba9400e8d5f6fa45bbb2d29e07b
Author: Jonh Wendell <jwendell gnome org>
Date: Sun Jul 12 02:18:12 2009 +0100
Second step (in a total of XX) towards plugin support.
It's building and running now, but still not functional and crashing
a lot. Tomorrow I'll continue my work.
configure.ac | 1 +
plugins/vnc/Makefile.am | 11 +--
plugins/vnc/vinagre-vnc-connection.c | 2 +
plugins/vnc/vinagre-vnc-plugin.c | 7 ++
{vinagre => plugins/vnc}/vinagre-vnc-tab.c | 10 +-
{vinagre => plugins/vnc}/vinagre-vnc-tab.h | 2 +-
vinagre/Makefile.am | 20 ++++-
vinagre/vinagre-main.c | 5 +-
vinagre/vinagre-mdns.c | 131 +++++++++++++++++++++++-----
vinagre/vinagre-mdns.h | 8 +-
vinagre/vinagre-plugin.c | 16 ++++
vinagre/vinagre-plugin.h | 2 +
vinagre/vinagre-plugins-engine.c | 18 +++-
vinagre/vinagre-tab.c | 9 ++-
14 files changed, 195 insertions(+), 47 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index e16be18..b7b179e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,6 +78,7 @@ AC_SUBST(VINAGRE_LIBS)
PKG_CHECK_MODULES(VNC, \
gtk-vnc-1.0 >= $GTK_VNC_REQUIRED \
+ libglade-2.0 >= $LIBGLADE_REQUIRED \
libxml-2.0
)
AC_SUBST(VNC_CFLAGS)
diff --git a/plugins/vnc/Makefile.am b/plugins/vnc/Makefile.am
index fd163c7..682c0f0 100644
--- a/plugins/vnc/Makefile.am
+++ b/plugins/vnc/Makefile.am
@@ -3,17 +3,16 @@ plugindir = $(VINAGRE_PLUGINS_LIBS_DIR)
INCLUDES = \
-I$(top_srcdir) \
- $(VNC_CFLAGS) \
+ $(VNC_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
plugin_LTLIBRARIES = libvnc.la
-libvnc_la_SOURCES = \
- vinagre-vnc-plugin.h \
- vinagre-vnc-plugin.c \
- vinagre-vnc-connection.h \
- vinagre-vnc-connection.c
+libvnc_la_SOURCES = \
+ vinagre-vnc-plugin.h vinagre-vnc-plugin.c \
+ vinagre-vnc-connection.h vinagre-vnc-connection.c \
+ vinagre-vnc-tab.h vinagre-vnc-tab.c
libvnc_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libvnc_la_LIBADD = $(VNC_LIBS)
diff --git a/plugins/vnc/vinagre-vnc-connection.c b/plugins/vnc/vinagre-vnc-connection.c
index 8ecca4c..6d18883 100644
--- a/plugins/vnc/vinagre-vnc-connection.c
+++ b/plugins/vnc/vinagre-vnc-connection.c
@@ -52,6 +52,8 @@ vinagre_vnc_connection_init (VinagreVncConnection *conn)
conn->priv->view_only = FALSE;
conn->priv->scaling = FALSE;
conn->priv->shared = -1;
+
+ vinagre_connection_set_protocol (VINAGRE_CONNECTION (conn), "vnc");
}
static void
diff --git a/plugins/vnc/vinagre-vnc-plugin.c b/plugins/vnc/vinagre-vnc-plugin.c
index cb755a5..d4f2d27 100644
--- a/plugins/vnc/vinagre-vnc-plugin.c
+++ b/plugins/vnc/vinagre-vnc-plugin.c
@@ -72,6 +72,12 @@ impl_get_protocol (VinagrePlugin *plugin)
return "vnc";
}
+static const gchar *
+impl_get_mdns_service (VinagrePlugin *plugin)
+{
+ return "_rfb._tcp";
+}
+
static VinagreConnection *
impl_new_connection (VinagrePlugin *plugin)
{
@@ -202,5 +208,6 @@ vinagre_vnc_plugin_class_init (VinagreVncPluginClass *klass)
plugin_class->get_protocol = impl_get_protocol;
plugin_class->new_connection = impl_new_connection;
plugin_class->new_connection_from_file = impl_new_connection_from_file;
+ plugin_class->get_mdns_service = impl_get_mdns_service;
}
/* vim: set ts=8: */
diff --git a/vinagre/vinagre-vnc-tab.c b/plugins/vnc/vinagre-vnc-tab.c
similarity index 99%
rename from vinagre/vinagre-vnc-tab.c
rename to plugins/vnc/vinagre-vnc-tab.c
index 61300c6..25d6e9d 100644
--- a/vinagre/vinagre-vnc-tab.c
+++ b/plugins/vnc/vinagre-vnc-tab.c
@@ -24,10 +24,11 @@
#include <vncdisplay.h>
#include <gdk/gdkkeysyms.h>
+#include <vinagre/vinagre-utils.h>
+#include <vinagre/vinagre-prefs.h>
+
#include "vinagre-vnc-tab.h"
#include "vinagre-vnc-connection.h"
-#include "vinagre-utils.h"
-#include "vinagre-prefs.h"
#define VINAGRE_VNC_TAB_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), VINAGRE_TYPE_VNC_TAB, VinagreVncTabPrivate))
@@ -119,7 +120,6 @@ vnc_get_initialized_actions (VinagreTab *tab)
static gchar *
vnc_tab_get_tooltip (VinagreTab *tab)
{
- gchar *tip;
VinagreVncTab *vnc_tab = VINAGRE_VNC_TAB (tab);
VinagreConnection *conn = vinagre_tab_get_conn (tab);
@@ -776,7 +776,6 @@ vnc_tab_clipboard_cb (GtkClipboard *cb, GdkEvent *event, VinagreVncTab *vnc_tab)
static void
vinagre_vnc_tab_init (VinagreVncTab *vnc_tab)
{
- GtkAction *action;
GtkClipboard *cb;
vnc_tab->priv = VINAGRE_VNC_TAB_GET_PRIVATE (vnc_tab);
@@ -976,7 +975,7 @@ vinagre_vnc_tab_get_original_width (VinagreVncTab *tab)
return -1;
}
-
+/*
typedef struct _VinagrePrefSize {
gint width, height;
gulong sig_id;
@@ -1020,6 +1019,7 @@ vinagre_widget_set_preferred_size (GtkWidget *widget, gint width,
gtk_widget_queue_resize (widget);
}
+*/
void
vinagre_vnc_tab_original_size (VinagreVncTab *tab)
diff --git a/vinagre/vinagre-vnc-tab.h b/plugins/vnc/vinagre-vnc-tab.h
similarity index 98%
rename from vinagre/vinagre-vnc-tab.h
rename to plugins/vnc/vinagre-vnc-tab.h
index 9c83488..7f6eddb 100644
--- a/vinagre/vinagre-vnc-tab.h
+++ b/plugins/vnc/vinagre-vnc-tab.h
@@ -22,7 +22,7 @@
#ifndef __VINAGRE_VNC_TAB_H__
#define __VINAGRE_VNC_TAB_H__
-#include "vinagre-tab.h"
+#include <vinagre/vinagre-tab.h>
G_BEGIN_DECLS
diff --git a/vinagre/Makefile.am b/vinagre/Makefile.am
index 4cc011a..449a129 100644
--- a/vinagre/Makefile.am
+++ b/vinagre/Makefile.am
@@ -47,7 +47,6 @@ INST_H_FILES = \
vinagre-tab.h \
vinagre-ui.h \
vinagre-utils.h \
- vinagre-vnc-tab.h \
vinagre-window.h \
$(NULL)
@@ -86,7 +85,6 @@ libvinagre_la_SOURCES = \
vinagre-prefs.c \
vinagre-tab.c \
vinagre-utils.c \
- vinagre-vnc-tab.c \
vinagre-window.c \
$(NOINST_H_FILES) \
$(INST_H_FILES) \
@@ -151,12 +149,29 @@ vinagre_applet_CFLAGS = \
vinagre_applet_SOURCES = \
vinagre-applet.c \
vinagre-bookmarks.h vinagre-bookmarks.c \
+ vinagre-bookmarks-ui.h vinagre-bookmarks-ui.c \
vinagre-connection.h vinagre-connection.c \
vinagre-utils.h vinagre-utils.c \
vinagre-enums.h vinagre-enums.c \
vinagre-bookmarks-entry.h vinagre-bookmarks-entry.c \
vinagre-bookmarks-tree.h vinagre-bookmarks-tree.c \
vinagre-bookmarks-migration.h vinagre-bookmarks-migration.c \
+ vinagre-plugins-engine.h vinagre-plugins-engine.c \
+ vinagre-plugin.h vinagre-plugin.c \
+ vinagre-plugin-loader.h vinagre-plugin-loader.c \
+ vinagre-plugin-manager.h vinagre-plugin-manager.c \
+ vinagre-debug.h vinagre-debug.c \
+ vinagre-plugin-info.h vinagre-plugin-info.c \
+ vinagre-window.h vinagre-window.c \
+ vinagre-commands.h vinagre-commands.c \
+ vinagre-notebook.h vinagre-notebook.c \
+ vinagre-tab.h vinagre-tab.c \
+ vinagre-prefs.h vinagre-prefs.c \
+ vinagre-app.h vinagre-app.c \
+ vinagre-object-module.h vinagre-object-module.c \
+ vinagre-dirs.h vinagre-dirs.c \
+ vinagre-fav.h vinagre-fav.c \
+ vinagre-connect.h vinagre-connect.c \
$(NULL)
if AVAHI
@@ -167,6 +182,7 @@ vinagre_applet_LDADD = \
$(APPLET_LIBS) \
$(VINAGRE_LIBS) \
$(AVAHI_LIBS) \
+ view/libview.la \
$(NULL)
diff --git a/vinagre/vinagre-main.c b/vinagre/vinagre-main.c
index 78867cc..140a45a 100644
--- a/vinagre/vinagre-main.c
+++ b/vinagre/vinagre-main.c
@@ -151,7 +151,7 @@ int main (int argc, char **argv) {
/* Init plugins engine */
vinagre_debug_message (DEBUG_APP, "Init plugins");
engine = vinagre_plugins_engine_get_default ();
- plugins = (const GSList *) vinagre_plugins_engine_get_plugin_list (engine);
+ plugins = (GSList *) vinagre_plugins_engine_get_plugin_list (engine);
/* Setup command line options */
context = g_option_context_new (_("- Remote Desktop Viewer"));
@@ -163,6 +163,9 @@ int main (int argc, char **argv) {
GOptionGroup *group;
VinagrePluginInfo *info = VINAGRE_PLUGIN_INFO (l->data);
+ if (!vinagre_plugin_info_is_active (info))
+ continue;
+
group = vinagre_plugin_get_context_group (info->plugin);
if (group)
g_option_context_add_group (context, group);
diff --git a/vinagre/vinagre-mdns.c b/vinagre/vinagre-mdns.c
index fb0e9d6..0aaf831 100644
--- a/vinagre/vinagre-mdns.c
+++ b/vinagre/vinagre-mdns.c
@@ -18,18 +18,29 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "vinagre-mdns.h"
-#include "vinagre-connection.h"
-#include "vinagre-bookmarks-entry.h"
#include <avahi-gobject/ga-service-browser.h>
#include <avahi-gobject/ga-service-resolver.h>
#include <glib/gi18n.h>
+#include "vinagre-mdns.h"
+#include "vinagre-connection.h"
+#include "vinagre-bookmarks-entry.h"
+#include "vinagre-plugins-engine.h"
+#include "vinagre-plugin.h"
+#include "vinagre-plugin-info.h"
+#include "vinagre-plugin-info-priv.h"
+
+typedef struct
+{
+ GaServiceBrowser *browser;
+ VinagrePluginInfo *info;
+} BrowserEntry;
+
struct _VinagreMdnsPrivate
{
GSList *entries;
- GaServiceBrowser *browser;
GaClient *client;
+ GHashTable *browsers;
};
enum
@@ -59,8 +70,16 @@ mdns_resolver_found (GaServiceResolver *resolver,
{
VinagreConnection *conn;
VinagreBookmarksEntry *entry;
+ BrowserEntry *b_entry;
- conn = vinagre_connection_new (VINAGRE_CONNECTION_PROTOCOL_VNC);
+ b_entry = g_hash_table_lookup (mdns->priv->browsers, type);
+ if (!b_entry)
+ {
+ g_error ("Service name not found in mDNS resolver hash table. This probably is a bug somewhere.");
+ return;
+ }
+
+ conn = vinagre_plugin_new_connection (b_entry->info->plugin);
g_object_set (conn,
"name", name,
"port", port,
@@ -151,39 +170,107 @@ mdns_browser_del_cb (GaServiceBrowser *browser,
}
static void
-vinagre_mdns_init (VinagreMdns *mdns)
+destroy_browser_entry (BrowserEntry *entry)
{
- GError *error = NULL;
+ g_object_unref (entry->browser);
+ _vinagre_plugin_info_unref (entry->info);
+ g_free (entry);
+}
- mdns->priv = G_TYPE_INSTANCE_GET_PRIVATE (mdns, VINAGRE_TYPE_MDNS, VinagreMdnsPrivate);
+static void
+vinagre_mdns_add_service (VinagrePluginInfo *info,
+ VinagreMdns *mdns)
+{
+ GaServiceBrowser *browser;
+ GError *error = NULL;
+ const gchar *service;
+ BrowserEntry *entry;
+ VinagrePlugin *plugin;
- mdns->priv->entries = NULL;
- mdns->priv->browser = ga_service_browser_new ("_rfb._tcp");
- mdns->priv->client = ga_client_new (GA_CLIENT_FLAG_NO_FLAGS);
+ service = vinagre_plugin_get_mdns_service (info->plugin);
+ if (!service)
+ return;
+
+ entry = g_hash_table_lookup (mdns->priv->browsers, service);
+ if (entry)
+ {
+ g_warning (_("Plugin %s has already registered a browser for service %s."),
+ info->name,
+ service);
+ return;
+ }
- g_signal_connect (mdns->priv->browser,
+ browser = ga_service_browser_new ((gchar *)service);
+ if (!browser)
+ {
+ g_warning (_("Failed to add mDNS browser for service %s."), service);
+ return;
+ }
+ g_signal_connect (browser,
"new-service",
G_CALLBACK (mdns_browser_new_cb),
mdns);
- g_signal_connect (mdns->priv->browser,
+ g_signal_connect (browser,
"removed-service",
G_CALLBACK (mdns_browser_del_cb),
mdns);
- if (!ga_client_start (mdns->priv->client, &error))
+ if (!ga_service_browser_attach (browser,
+ mdns->priv->client,
+ &error))
{
g_warning (_("Failed to browse for hosts: %s\n"), error->message);
g_error_free (error);
return;
}
- if (!ga_service_browser_attach (mdns->priv->browser,
- mdns->priv->client,
- &error))
+ entry = g_new (BrowserEntry, 1);
+ entry->browser = g_object_ref (browser);
+ _vinagre_plugin_info_ref (info);
+ entry->info = info;
+ g_hash_table_insert (mdns->priv->browsers, (gpointer)service, entry);
+}
+
+static void
+plugin_activated_cb (VinagrePluginsEngine *engine,
+ VinagrePluginInfo *info,
+ VinagreMdns *mdns)
+{
+ vinagre_mdns_add_service (info, mdns);
+}
+
+static void
+vinagre_mdns_init (VinagreMdns *mdns)
+{
+ GError *error = NULL;
+ GSList *plugins;
+ VinagrePluginsEngine *engine;
+
+ mdns->priv = G_TYPE_INSTANCE_GET_PRIVATE (mdns, VINAGRE_TYPE_MDNS, VinagreMdnsPrivate);
+
+ mdns->priv->entries = NULL;
+ mdns->priv->browsers = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)destroy_browser_entry);
+ mdns->priv->client = ga_client_new (GA_CLIENT_FLAG_NO_FLAGS);
+
+ if (!ga_client_start (mdns->priv->client, &error))
{
- g_warning (_("Failed to browse for hosts: %s\n"), error->message);
+ g_warning (_("Failed to initialize mDNS browser: %s\n"), error->message);
g_error_free (error);
+ g_object_unref (mdns->priv->client);
+ mdns->priv->client = NULL;
+ return;
}
+
+ engine = vinagre_plugins_engine_get_default ();
+ plugins = (GSList *)vinagre_plugins_engine_get_plugin_list (engine);
+ g_slist_foreach (plugins,
+ (GFunc)vinagre_mdns_add_service,
+ mdns);
+
+ g_signal_connect (engine,
+ "activate-plugin",
+ G_CALLBACK (plugin_activated_cb),
+ mdns);
}
static void
@@ -191,10 +278,10 @@ vinagre_mdns_dispose (GObject *object)
{
VinagreMdns *mdns = VINAGRE_MDNS (object);
- if (mdns->priv->browser)
+ if (mdns->priv->browsers)
{
- g_object_unref (mdns->priv->browser);
- mdns->priv->browser = NULL;
+ g_hash_table_unref (mdns->priv->browsers);
+ mdns->priv->browsers = NULL;
}
if (mdns->priv->client)
@@ -251,3 +338,5 @@ vinagre_mdns_get_all (VinagreMdns *mdns)
return mdns->priv->entries;
}
+
+/* vim: set ts=8: */
diff --git a/vinagre/vinagre-mdns.h b/vinagre/vinagre-mdns.h
index 8b28bd2..ec805fd 100644
--- a/vinagre/vinagre-mdns.h
+++ b/vinagre/vinagre-mdns.h
@@ -2,7 +2,7 @@
* vinagre-mdns.h
* This file is part of vinagre
*
- * Copyright (C) Jonh Wendell 2008 <wendell bani com br>
+ * Copyright (C) Jonh Wendell 2008,2009 <wendell bani com br>
*
* 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 the
@@ -51,10 +51,10 @@ struct _VinagreMdns
VinagreMdnsPrivate *priv;
};
-GType vinagre_mdns_get_type (void) G_GNUC_CONST;
+GType vinagre_mdns_get_type (void) G_GNUC_CONST;
-VinagreMdns *vinagre_mdns_get_default (void);
-GSList *vinagre_mdns_get_all (VinagreMdns *mdns);
+VinagreMdns *vinagre_mdns_get_default (void);
+GSList *vinagre_mdns_get_all (VinagreMdns *mdns);
G_END_DECLS
diff --git a/vinagre/vinagre-plugin.c b/vinagre/vinagre-plugin.c
index 8d594cd..89ba63b 100644
--- a/vinagre/vinagre-plugin.c
+++ b/vinagre/vinagre-plugin.c
@@ -162,6 +162,7 @@ vinagre_plugin_class_init (VinagrePluginClass *klass)
klass->get_default_port = default_get_default_port;
klass->new_connection = default_new_connection;
klass->new_connection_from_file = default_new_connection_from_file;
+ klass->get_mdns_service = default_get_protocol;
klass->create_configure_dialog = create_configure_dialog;
klass->is_configurable = is_configurable;
@@ -438,4 +439,19 @@ vinagre_plugin_get_default_port (VinagrePlugin *plugin)
return VINAGRE_PLUGIN_GET_CLASS (plugin)->get_default_port (plugin);
}
+/**
+ * vinagre_plugin_get_mdns_service
+ * @plugin: a #VinagrePlugin
+ *
+ *
+ * Returns: a mDNS service for this plugin, like rfb.tcp
+ */
+const gchar *
+vinagre_plugin_get_mdns_service (VinagrePlugin *plugin)
+{
+ g_return_val_if_fail (VINAGRE_IS_PLUGIN (plugin), NULL);
+
+ return VINAGRE_PLUGIN_GET_CLASS (plugin)->get_mdns_service (plugin);
+}
+
/* vim: set ts=8: */
diff --git a/vinagre/vinagre-plugin.h b/vinagre/vinagre-plugin.h
index 13bb464..37a709f 100644
--- a/vinagre/vinagre-plugin.h
+++ b/vinagre/vinagre-plugin.h
@@ -81,6 +81,7 @@ struct _VinagrePluginClass
const gchar *data,
gboolean use_bookmarks,
gchar **error_msg);
+ const gchar *(*get_mdns_service) (VinagrePlugin *plugin);
/* Plugins should not override this, it's handled automatically by
the VinagrePluginClass */
@@ -120,6 +121,7 @@ VinagreConnection *vinagre_plugin_new_connection_from_file (VinagrePlugin *plugi
const gchar *data,
gboolean use_bookmarks,
gchar **error_msg);
+const gchar *vinagre_plugin_get_mdns_service (VinagrePlugin *plugin);
/**
* VINAGRE_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE):
diff --git a/vinagre/vinagre-plugins-engine.c b/vinagre/vinagre-plugins-engine.c
index 5ca4a85..afcc935 100644
--- a/vinagre/vinagre-plugins-engine.c
+++ b/vinagre/vinagre-plugins-engine.c
@@ -260,13 +260,23 @@ add_loader (VinagrePluginsEngine *engine,
static void
activate_engine_plugins (VinagrePluginsEngine *engine)
{
- GSList *item;
+ GSList *active_plugins, *l;
vinagre_debug_message (DEBUG_PLUGINS, "Activating engine plugins");
- for (item = engine->priv->plugin_list; item; item = item->next)
- {
- VinagrePluginInfo *info = VINAGRE_PLUGIN_INFO (item->data);
+ g_object_get (vinagre_prefs_get_default (),
+ "active-plugins", &active_plugins,
+ NULL);
+
+ for (l = engine->priv->plugin_list; l; l = l->next)
+ {
+ VinagrePluginInfo *info = (VinagrePluginInfo*)l->data;
+
+ if (g_slist_find_custom (active_plugins,
+ vinagre_plugin_info_get_module_name (info),
+ (GCompareFunc)strcmp) == NULL)
+ continue;
+
if (vinagre_plugin_info_is_engine (info))
vinagre_plugins_engine_activate_plugin (engine, info);
}
diff --git a/vinagre/vinagre-tab.c b/vinagre/vinagre-tab.c
index 36b1fc8..ac14b24 100644
--- a/vinagre/vinagre-tab.c
+++ b/vinagre/vinagre-tab.c
@@ -443,11 +443,14 @@ vinagre_tab_init (VinagreTab *tab)
GtkWidget *
vinagre_tab_new (VinagreConnection *conn, VinagreWindow *window)
{
- switch (vinagre_connection_get_protocol (conn))
+/* switch (vinagre_connection_get_protocol (conn))
{
case VINAGRE_CONNECTION_PROTOCOL_VNC: return GTK_WIDGET (vinagre_vnc_tab_new (conn, window));
default: g_assert_not_reached ();
}
+*/
+// TODO:
+ return NULL;
}
gchar *
@@ -592,7 +595,7 @@ vinagre_tab_find_credentials_in_keyring (VinagreTab *tab, gchar **username, gcha
NULL, /* domain */
vinagre_connection_get_host (tab->priv->conn), /* server */
NULL, /* object */
- vinagre_connection_get_protocol_as_string (tab->priv->conn), /* protocol */
+ vinagre_connection_get_protocol (tab->priv->conn), /* protocol */
NULL, /* authtype */
vinagre_connection_get_port (tab->priv->conn), /* port */
&matches);
@@ -631,7 +634,7 @@ vinagre_tab_save_credentials_in_keyring (VinagreTab *tab)
NULL, /* domain */
vinagre_connection_get_host (tab->priv->conn), /* server */
NULL, /* object */
- vinagre_connection_get_protocol_as_string (tab->priv->conn), /* protocol */
+ vinagre_connection_get_protocol (tab->priv->conn), /* protocol */
NULL, /* authtype */
vinagre_connection_get_port (tab->priv->conn), /* port */
vinagre_connection_get_password (tab->priv->conn), /* password */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]