[913] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

[D-O-H] r899 - in branches/barnowl_sqlite: . owl owl/perl/modules/IRC owl/perl/modules/IRC/lib/BarnOwl/Module owl/perl/modules/IRC/lib/BarnOwl/Module/IRC

daemon@ATHENA.MIT.EDU (nelhage@MIT.EDU)
Thu Oct 29 18:11:03 2009

Resent-From: nelhage@mit.edu
Resent-To: barnowl-dev-mtg@charon.mit.edu
To: dirty-owl-hackers@mit.edu
From: nelhage@MIT.EDU
Reply-to: dirty-owl-hackers@MIT.EDU
Date: Tue, 22 Jan 2008 22:41:58 -0500 (EST)

Author: nelhage
Date: 2008-01-22 22:41:58 -0500 (Tue, 22 Jan 2008)
New Revision: 899

Modified:
   branches/barnowl_sqlite/
   branches/barnowl_sqlite/owl/Makefile.in
   branches/barnowl_sqlite/owl/global.c
   branches/barnowl_sqlite/owl/owl.c
   branches/barnowl_sqlite/owl/perl/modules/IRC/
   branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC.pm
   branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm
   branches/barnowl_sqlite/owl/perlwrap.pm
   branches/barnowl_sqlite/owl/stylefunc.c
Log:
Merged revisions 880-898 via svnmerge from 
svn+ssh://lunatique.mit.edu/mit/barnowl/src/svn/trunk

........
  r881 | nelhage | 2008-01-16 02:59:06 -0500 (Wed, 16 Jan 2008) | 1 line
  
  Move oneline style to perl. closes 43
........
  r889 | nelhage | 2008-01-16 22:03:00 -0500 (Wed, 16 Jan 2008) | 4 lines
  
  
  Rewrite ::Connection to not subclass Net::IRC::Connection to avoid
  stupid namespace conflicts
........
  r890 | nelhage | 2008-01-16 22:07:42 -0500 (Wed, 16 Jan 2008) | 2 lines
  
  svn:ignore for great justice
........
  r894 | asedeno | 2008-01-17 02:13:44 -0500 (Thu, 17 Jan 2008) | 2 lines
  
  dropping one unnecessary time(NULL) call.
........
  r898 | geofft | 2008-01-18 08:58:53 -0500 (Fri, 18 Jan 2008) | 4 lines
  
  * minor changes to IRC
  * run ./svkversion only once rather than at every cc
  * fix one-line style to format logouts, not just logins
........



Property changes on: branches/barnowl_sqlite
___________________________________________________________________
Name: svnmerge-integrated
   - /trunk:1-879
   + /trunk:1-898

Modified: branches/barnowl_sqlite/owl/Makefile.in
===================================================================
--- branches/barnowl_sqlite/owl/Makefile.in	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/Makefile.in	2008-01-23 03:41:58 UTC (rev 899)
@@ -10,7 +10,7 @@
 
 CC=@CC@
 LIBS=@LIBS@ -L./libfaim -lfaim
-CFLAGS=@CFLAGS@ -I. -I./libfaim -DDATADIR=\"${datadir}\" -DOWL_SVN_REVNO=`./svkversion`
+CFLAGS=@CFLAGS@ -I. -I./libfaim -DDATADIR=\"${datadir}\" -DOWL_SVN_REVNO=$(shell ./svkversion)
 LDFLAGS=@LDFLAGS@
 XSUBPPDIR=@XSUBPPDIR@
 XSUBPPFLAGS=@XSUBPPFLAGS@

Modified: branches/barnowl_sqlite/owl/global.c
===================================================================
--- branches/barnowl_sqlite/owl/global.c	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/global.c	2008-01-23 03:41:58 UTC (rev 899)
@@ -478,8 +478,8 @@
   return(g->lastinputtime);
 }
 
-void owl_global_update_lastinputtime(owl_global *g) {
-  g->lastinputtime = time(NULL);
+void owl_global_set_lastinputtime(owl_global *g, time_t time) {
+  g->lastinputtime = time;
 }
 
 time_t owl_global_get_idletime(owl_global *g) {

Modified: branches/barnowl_sqlite/owl/owl.c
===================================================================
--- branches/barnowl_sqlite/owl/owl.c	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/owl.c	2008-01-23 03:41:58 UTC (rev 899)
@@ -256,9 +256,6 @@
   s=owl_malloc(sizeof(owl_style));
   owl_style_create_internal(s, "basic", &owl_stylefunc_basic, "Basic message formatting.");
   owl_global_add_style(&g, s);
-  s=owl_malloc(sizeof(owl_style));
-  owl_style_create_internal(s, "oneline", &owl_stylefunc_oneline, "Formats for one-line-per-message");
-  owl_global_add_style(&g, s);
 
   /* setup the default filters */
   /* the personal filter will need to change again when AIM chat's are
@@ -544,7 +541,7 @@
     if (j==ERR) {
       usleep(10000);
     } else {
-      owl_global_update_lastinputtime(&g);
+      owl_global_set_lastinputtime(&g, now);
       /* find and activate the current keymap.
        * TODO: this should really get fixed by activating
        * keymaps as we switch between windows... 


Property changes on: branches/barnowl_sqlite/owl/perl/modules/IRC
___________________________________________________________________
Name: svn:ignore
   + IRC.par
META.yml
Makefile
pm_to_blib
blib
inc


Modified: branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm
===================================================================
--- branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm	2008-01-23 03:41:58 UTC (rev 899)
@@ -9,46 +9,61 @@
 
 =head1 DESCRIPTION
 
-This module is a Net::IRC::Connection subclass for BarnOwl's IRC
+This module is a wrapper around Net::IRC::Connection for BarnOwl's IRC
 support
 
 =cut
 
-use base qw(Net::IRC::Connection Class::Accessor Exporter);
-__PACKAGE__->mk_accessors(qw(alias channels owl_connected owl_motd));
+use Net::IRC::Connection;
+
+use base qw(Class::Accessor Exporter);
+__PACKAGE__->mk_accessors(qw(conn alias channels connected motd));
 our @EXPORT_OK = qw(&is_private);
 
 use BarnOwl;
 
+BEGIN {
+    no strict 'refs';
+    my @delegate = qw(nick server);
+    for my $meth (@delegate) {
+        *{"BarnOwl::Module::IRC::Connection::$meth"} = sub {
+            shift->conn->$meth(@_);
+        }
+    }
+};
+
 sub new {
     my $class = shift;
     my $irc = shift;
     my $alias = shift;
     my %args = (@_);
-    my $self = $class->SUPER::new($irc, %args);
+    my $conn = Net::IRC::Connection->new($irc, %args);
+    my $self = bless({}, $class);
+    $self->conn($conn);
     $self->alias($alias);
     $self->channels([]);
-    $self->owl_motd("");
-    $self->owl_connected(0);
-    bless($self, $class);
+    $self->motd("");
+    $self->connected(0);
 
-    $self->add_default_handler(sub { goto &on_event; });
-    $self->add_handler(['msg', 'notice', 'public', 'caction'],
-            sub { goto &on_msg });
-    $self->add_handler(['welcome', 'yourhost', 'created',
-            'luserclient', 'luserop', 'luserchannels', 'luserme'],
-            sub { goto &on_admin_msg });
-    $self->add_handler(['myinfo', 'map', 'n_local', 'n_global',
+    $self->conn->add_handler(376 => sub { shift; $self->on_connect(@_) });
+    $self->conn->add_default_handler(sub { shift; $self->on_event(@_) });
+    $self->conn->add_handler(['msg', 'notice', 'public', 'caction'],
+            sub { shift; $self->on_msg(@_) });
+    $self->conn->add_handler(['welcome', 'yourhost', 'created',
+            'luserclient', 'luserop', 'luserchannels', 'luserme',
+            'notice', 'error'],
+            sub { shift; $self->on_admin_msg(@_) });
+    $self->conn->add_handler(['myinfo', 'map', 'n_local', 'n_global',
             'luserconns'],
             sub { });
-    $self->add_handler(motdstart => sub { goto &on_motdstart });
-    $self->add_handler(motd      => sub { goto &on_motd });
-    $self->add_handler(endofmotd => sub { goto &on_endofmotd });
-    $self->add_handler(join      => sub { goto &on_join });
-    $self->add_handler(part      => sub { goto &on_part });
-    $self->add_handler(disconnect => sub { goto &on_disconnect });
-    $self->add_handler(nicknameinuse => sub { goto &on_nickinuse });
-    $self->add_handler(cping     => sub { goto &on_ping });
+    $self->conn->add_handler(motdstart => sub { shift; $self->on_motdstart(@_) });
+    $self->conn->add_handler(motd      => sub { shift; $self->on_motd(@_) });
+    $self->conn->add_handler(endofmotd => sub { shift; $self->on_endofmotd(@_) });
+    $self->conn->add_handler(join      => sub { shift; $self->on_join(@_) });
+    $self->conn->add_handler(part      => sub { shift; $self->on_part(@_) });
+    $self->conn->add_handler(disconnect => sub { shift; $self->on_disconnect(@_) });
+    $self->conn->add_handler(nicknameinuse => sub { shift; $self->on_nickinuse(@_) });
+    $self->conn->add_handler(cping     => sub { shift; $self->on_ping(@_) });
 
     return $self;
 }
@@ -96,7 +111,7 @@
 
 sub on_ping {
     my ($self, $evt) = @_;
-    $self->ctcp_reply($evt->nick, join (' ', ($evt->args)));
+    $self->conn->ctcp_reply($evt->nick, join (' ', ($evt->args)));
 }
 
 sub on_admin_msg {
@@ -109,26 +124,26 @@
 
 sub on_motdstart {
     my ($self, $evt) = @_;
-    $self->owl_motd(join "\n", cdr $evt->args);
+    $self->motd(join "\n", cdr $evt->args);
 }
 
 sub on_motd {
     my ($self, $evt) = @_;
-    $self->owl_motd(join "\n", $self->owl_motd, cdr $evt->args);
+    $self->motd(join "\n", $self->motd, cdr $evt->args);
 }
 
 sub on_endofmotd {
     my ($self, $evt) = @_;
-    $self->owl_motd(join "\n", $self->owl_motd, cdr $evt->args);
-    if(!$self->owl_connected) {
+    $self->motd(join "\n", $self->motd, cdr $evt->args);
+    if(!$self->connected) {
         BarnOwl::admin_message("IRC", "Connected to " .
                                $self->server . " (" . $self->alias . ")");
-        $self->owl_connected(1);
+        $self->connected(1);
         
     }
     BarnOwl::admin_message("IRC",
             BarnOwl::Style::boldify('MOTD for ' . $self->alias) . "\n"
-            . strip_irc_formatting($self->owl_motd));
+            . strip_irc_formatting($self->motd));
 }
 
 sub on_join {
@@ -162,8 +177,8 @@
     BarnOwl::admin_message("IRC",
                            "[" . $self->alias . "] " .
                            [$evt->args]->[1] . ": Nick already in use");
-    unless($self->owl_connected) {
-        $self->disconnect;
+    unless($self->connected) {
+        $self->conn->disconnect;
     }
 }
 

Modified: branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC.pm
===================================================================
--- branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC.pm	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/perl/modules/IRC/lib/BarnOwl/Module/IRC.pm	2008-01-23 03:41:58 UTC (rev 899)
@@ -64,7 +64,7 @@
 
 sub shutdown {
     for my $conn (values %ircnets) {
-        $conn->disconnect();
+        $conn->conn->disconnect();
     }
 }
 
@@ -161,14 +161,20 @@
         SSL       => $ssl
        );
 
-    $ircnets{$alias} = $conn;
+    if ($conn->connected) {
+        BarnOwl::admin_message("IRC", "Connected to $alias as $nick");
+        $ircnets{$alias} = $conn;
+    } else {
+        die("IRC::Connection->connect failed: $!");
+    }
+
     return;
 }
 
 sub cmd_disconnect {
     my $cmd = shift;
     my $conn = get_connection(\@_);
-    $conn->disconnect;
+    $conn->conn->disconnect;
     delete $ircnets{$conn->alias};
 }
 
@@ -190,7 +196,7 @@
     my $body = shift;
     # Strip whitespace. In the future -- send one message/line?
     $body =~ tr/\n\r/  /;
-    $conn->privmsg($to, $body);
+    $conn->conn->privmsg($to, $body);
     my $msg = BarnOwl::Message->new(
         type        => 'IRC',
         direction   => is_private($to) ? 'out' : 'in',
@@ -213,7 +219,7 @@
     my $chan = shift or die("Usage: $cmd channel\n");
     $channels{$chan} ||= [];
     push @{$channels{$chan}}, $conn;
-    $conn->join($chan);
+    $conn->conn->join($chan);
 }
 
 sub cmd_part {
@@ -221,34 +227,34 @@
     my $conn = get_connection(\@_);
     my $chan = get_channel(\@_) || die("Usage: $cmd <channel>\n");
     $channels{$chan} = [grep {$_ ne $conn} @{$channels{$chan} || []}];
-    $conn->part($chan);
+    $conn->conn->part($chan);
 }
 
 sub cmd_nick {
     my $cmd = shift;
     my $conn = get_connection(\@_);
     my $nick = shift or die("Usage: $cmd <new nick>\n");
-    $conn->nick($nick);
+    $conn->conn->nick($nick);
 }
 
 sub cmd_names {
     my $cmd = shift;
     my $conn = get_connection(\@_);
     my $chan = get_channel(\@_) || die("Usage: $cmd <channel>\n");
-    $conn->names($chan);
+    $conn->conn->names($chan);
 }
 
 sub cmd_whois {
     my $cmd = shift;
     my $conn = get_connection(\@_);
     my $who = shift || die("Usage: $cmd <user>\n");
-    $conn->whois($who);
+    $conn->conn->whois($who);
 }
 
 sub cmd_motd {
     my $cmd = shift;
     my $conn = get_connection(\@_);
-    $conn->motd;
+    $conn->conn->motd;
 }
 
 ################################################################################

Modified: branches/barnowl_sqlite/owl/perlwrap.pm
===================================================================
--- branches/barnowl_sqlite/owl/perlwrap.pm	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/perlwrap.pm	2008-01-23 03:41:58 UTC (rev 899)
@@ -947,11 +947,111 @@
     # replace newline followed by anything with
     # newline plus four spaces and that thing.
     $body =~ s/\n(.)/\n    $1/g;
-
+    # Trim trailing newlines.
+    $body =~ s/\n*$//;
     return "    ".$body;
 }
 
+package BarnOwl::Style::OneLine;
+################################################################################
+# Branching point for various formatting functions in this style.
+################################################################################
+use constant BASE_FORMAT => '%s %-13.13s %-11.11s %-12.12s ';
+sub format_message($) {
+  my $m = shift;
 
+#  if ( $m->is_zephyr ) {
+#    return format_zephyr($m);
+#  }
+  if ( $m->is_loginout ) {
+    return format_login($m);
+  }
+  elsif ( $m->is_ping) {
+    return format_ping($m);
+  }
+  elsif ( $m->is_admin || $m->is_loopback) {
+    return format_local($m);
+  }
+  else {
+    return format_chat($m);
+  }
+}
+
+BarnOwl::_create_style("oneline", "BarnOwl::Style::OneLine::format_message", "Formats for one-line-per-message");
+
+################################################################################
+
+sub format_login($) {
+  my $m = shift;
+  return sprintf(
+    BASE_FORMAT,
+    '<',
+    $m->type,
+    uc( $m->login ),
+    $m->pretty_sender)
+    . ($m->login_extra ? "at ".$m->login_extra : '');
+}
+
+sub format_ping($) {
+  my $m = shift;
+  return sprintf(
+    BASE_FORMAT,
+    '<',
+    $m->type,
+    'PING',
+    $m->pretty_sender)
+}
+
+sub format_chat($)
+{
+  my $m = shift;
+  my $dir = lc($m->{direction});
+  my $dirsym = '-';
+  if ($dir eq 'in') {
+    $dirsym = '<';
+  }
+  elsif ($dir eq 'out') {
+    $dirsym = '>';
+  }
+
+  my $line;
+  if ($m->is_personal) {
+    $line= sprintf(BASE_FORMAT,
+		   $dirsym,
+		   $m->type,
+		   '',
+		   ($dir eq 'out'
+		      ? $m->pretty_recipient
+		      : $m->pretty_sender));
+  }
+  else {
+    $line = sprintf(BASE_FORMAT,
+		    $dirsym,
+		    $m->context,
+		    $m->subcontext,
+		    ($dir eq 'out'
+		       ? $m->pretty_recipient
+		       : $m->pretty_sender));
+  }
+
+  my $body = $m->{body};
+  $body =~ tr/\n/ /;
+  $line .= $body;
+  $line = BarnOwl::Style::boldify($line) if ($m->is_personal && lc($m->direction) eq 'in');
+  return $line;
+}
+
+# Format locally generated messages
+sub format_local($)
+{
+  my $m = shift;
+  my $type = uc($m->{type});
+  my $line = sprintf(BASE_FORMAT, '<', $type, '', '');
+  my $body = $m->{body};
+  $body =~ tr/\n/ /;
+  return $line.$body;
+}
+
 package BarnOwl::Style;
 
 # This takes a zephyr to be displayed and modifies it to be displayed

Modified: branches/barnowl_sqlite/owl/stylefunc.c
===================================================================
--- branches/barnowl_sqlite/owl/stylefunc.c	2008-01-18 13:58:53 UTC (rev 898)
+++ branches/barnowl_sqlite/owl/stylefunc.c	2008-01-23 03:41:58 UTC (rev 899)
@@ -217,128 +217,3 @@
     owl_free(header);
   }
 }
-
-void owl_stylefunc_oneline(owl_fmtext *fm, owl_message *m)
-{
-  char *tmp;
-  char *baseformat="%s %-13.13s %-11.11s %-12.12s ";
-  char *sender, *recip;
-
-  sender=short_zuser(owl_message_get_sender(m));
-  recip=short_zuser(owl_message_get_recipient(m));
-  
-  if (owl_message_is_type_zephyr(m)) {
-#ifdef HAVE_LIBZEPHYR
-    owl_fmtext_append_spaces(fm, OWL_TAB);
-
-    if (owl_message_is_loginout(m)) {
-      char *host, *tty;
-      
-      host=owl_message_get_attribute_value(m, "loginhost");
-      tty=owl_message_get_attribute_value(m, "logintty");
-
-      if (owl_message_is_login(m)) {
-	tmp=owl_sprintf(baseformat, "<", owl_message_is_pseudo(m)?"LOGIN-P":"LOGIN", "", sender);
-	owl_fmtext_append_normal(fm, tmp);
-	owl_free(tmp);
-      } else if (owl_message_is_logout(m)) {
-	tmp=owl_sprintf(baseformat, "<", owl_message_is_pseudo(m)?"LOGOUT-P":"LOGOUT", "", sender);
-	owl_fmtext_append_normal(fm, tmp);
-	owl_free(tmp);
-      }
-
-      owl_fmtext_append_normal(fm, "at ");
-      owl_fmtext_append_normal(fm, host ? host : "");
-      owl_fmtext_append_normal(fm, " ");
-      owl_fmtext_append_normal(fm, tty ? tty : "");
-      owl_fmtext_append_normal(fm, "\n");
-
-    } else if (owl_message_is_ping(m)) {
-      tmp=owl_sprintf(baseformat, "<", "PING", "", sender);
-      owl_fmtext_append_normal(fm, tmp);
-      owl_fmtext_append_normal(fm, "\n");
-      owl_free(tmp);
-
-    } else {
-      if (owl_message_is_direction_in(m)) {
-	tmp=owl_sprintf(baseformat, "<", owl_message_get_class(m), owl_message_get_instance(m), sender);
-      } else if (owl_message_is_direction_out(m)) {
-	tmp=owl_sprintf(baseformat, ">", owl_message_get_class(m), owl_message_get_instance(m), recip);
-      } else {
-	tmp=owl_sprintf(baseformat, "-", owl_message_get_class(m), owl_message_get_instance(m), sender);
-      }
-      owl_fmtext_append_normal(fm, tmp);
-      if (tmp) owl_free(tmp);
-      
-      tmp=owl_strdup(owl_message_get_body(m));
-      owl_text_tr(tmp, '\n', ' ');
-      owl_fmtext_append_ztext(fm, tmp);
-      owl_fmtext_append_normal(fm, "\n");
-      if (tmp) owl_free(tmp);
-    }
-      
-    /* make personal messages bold for smaat users */
-    if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES) &&
-	owl_message_is_personal(m) &&
-	owl_message_is_direction_in(m)) {
-      owl_fmtext_addattr(fm, OWL_FMTEXT_ATTR_BOLD);
-    }
-
-    owl_free(sender);
-    owl_free(recip);
-#endif
-  } else if (owl_message_is_type_aim(m)) {
-    owl_fmtext_append_spaces(fm, OWL_TAB);
-    if (owl_message_is_login(m)) {
-      tmp=owl_sprintf(baseformat, "<", "AIM LOGIN", "", owl_message_get_sender(m));
-      owl_fmtext_append_normal(fm, tmp);
-      owl_fmtext_append_normal(fm, "\n");
-      if (tmp) owl_free(tmp);
-    } else if (owl_message_is_logout(m)) {
-      tmp=owl_sprintf(baseformat, "<", "AIM LOGOUT", "", owl_message_get_sender(m));
-      owl_fmtext_append_normal(fm, tmp);
-      owl_fmtext_append_normal(fm, "\n");
-      if (tmp) owl_free(tmp);
-    } else {
-      if (owl_message_is_direction_in(m)) {
-	tmp=owl_sprintf(baseformat, "<", "AIM", "", owl_message_get_sender(m));
-	owl_fmtext_append_normal(fm, tmp);
-	if (tmp) owl_free(tmp);
-      } else if (owl_message_is_direction_out(m)) {
-	tmp=owl_sprintf(baseformat, ">", "AIM", "", owl_message_get_recipient(m));
-	owl_fmtext_append_normal(fm, tmp);
-	if (tmp) owl_free(tmp);
-      }
-      
-      tmp=owl_strdup(owl_message_get_body(m));
-      owl_text_tr(tmp, '\n', ' ');
-      owl_fmtext_append_normal(fm, tmp);
-      owl_fmtext_append_normal(fm, "\n");
-      if (tmp) owl_free(tmp);
-
-      /* make personal messages bold for smaat users */
-      if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES) && owl_message_is_direction_in(m)) {
-	owl_fmtext_addattr(fm, OWL_FMTEXT_ATTR_BOLD);
-      }
-    }
-  } else if (owl_message_is_type_admin(m)) {
-    owl_fmtext_append_spaces(fm, OWL_TAB);
-    owl_fmtext_append_normal(fm, "< ADMIN                                  ");
-    
-    tmp=owl_strdup(owl_message_get_body(m));
-    owl_text_tr(tmp, '\n', ' ');
-    owl_fmtext_append_normal(fm, tmp);
-    owl_fmtext_append_normal(fm, "\n");
-    if (tmp) owl_free(tmp);
-  } else {
-    owl_fmtext_append_spaces(fm, OWL_TAB);
-    owl_fmtext_append_normal(fm, "< LOOPBACK                               ");
-    
-    tmp=owl_strdup(owl_message_get_body(m));
-    owl_text_tr(tmp, '\n', ' ');
-    owl_fmtext_append_normal(fm, tmp);
-    owl_fmtext_append_normal(fm, "\n");
-    if (tmp) owl_free(tmp);
-  }    
-
-}


home help back first fref pref prev next nref lref last post