Index: Makefile.in
===================================================================
--- Makefile.in	(revision 9c7a701363179369d764454b0d99e559ab89ed9e)
+++ Makefile.in	(revision 864ed359c1c6fbc341ca8d3a273cb7c2ae4e0875)
@@ -25,5 +25,5 @@
      regex.c history.c view.c dict.c variable.c filterelement.c pair.c \
      keypress.c keymap.c keybinding.c cmd.c context.c zcrypt.c \
-     aim.c buddy.c buddylist.c timer.c style.c stylefunc.c errqueue.c \
+     aim.c buddy.c buddylist.c timer.c style.c errqueue.c \
      zbuddylist.c muxevents.c popexec.c obarray.c select.c wcwidth.c \
      glib_compat.c
@@ -48,7 +48,4 @@
 HEADERS=$(GEN_H) owl.h config.h test.h
 
-%.o: %.c $(HEADERS)
-	$(CC) -c $(CFLAGS) $< -o $@
-
 $(EXE): $(AUTOGEN) $(OBJS) owl.o libfaim
 	$(ATHSTATIC) $(CC) -o $(EXE) owl.o $(OBJS) $(LDFLAGS) $(LIBS)
@@ -56,4 +53,12 @@
 tester: $(AUTOGEN) $(OBJS) tester.o
 	$(ATHSTATIC) $(CC) -o tester tester.o $(OBJS) $(LDFLAGS) $(LIBS)
+
+%.o: %.c $(HEADERS)
+	$(CC) -c $(CFLAGS) $< -o $@
+
+# zcrypt is old crufty DES code I don't want to touch
+# Disable all warnings when compiling it
+zcrypt.o: zcrypt.c $(HEADERS)
+	$(CC) -c $(CFLAGS) $< -w -o $@
 
 test: tester
@@ -100,5 +105,5 @@
 #owl_prototypes.h:
 
-.PHONY: tags clean distclean proto test
+.PHONY: tags clean distclean proto test check-syntax
 
 tags: TAGS
@@ -107,6 +112,5 @@
 	etags $(BASE_SRCS) $(OWL_SRC) $(TESTER_SRC) $(GEN_C) owl.h $(GEN_H)
 
-$(BASE_OBJS) varstubs.h:: owl.h config.h owl_prototypes.h
-#$(BASE_OBJS) varstubs.h:: owl.h config.h
+$(BASE_OBJS) varstubs.h: owl.h config.h owl_prototypes.h
 
 libfaim: libfaim/libfaim.a
@@ -135,2 +139,6 @@
 installdirs: mkinstalldirs
 	${srcdir}/mkinstalldirs ${DESTDIR}${bindir} ${DESTDIR}${mandir}/man1 ${DESTDIR}${datadir}
+
+# For emacs flymake-mode
+check-syntax: proto
+	$(CC) $(CFLAGS) -Wall -Wextra -pedantic -fsyntax-only $(CHK_SOURCES)
Index: aim.c
===================================================================
--- aim.c	(revision 34509d514dfa9ee441febffc6d61e108962d1507)
+++ aim.c	(revision e3e6cff9f72f2e4f2c72c2a48f95e45db859298d)
@@ -1452,5 +1452,6 @@
      *
      */
-    strncpy(realmsg, args->msg, sizeof(realmsg));
+    if (args->msg && args->msglen)
+      strncpy(realmsg, args->msg, sizeof(realmsg));
   }
 
Index: commands.c
===================================================================
--- commands.c	(revision 36172860060e404e761fc6fd5503c09ef88bd83d)
+++ commands.c	(revision 864ed359c1c6fbc341ca8d3a273cb7c2ae4e0875)
@@ -101,12 +101,4 @@
 	      "Use 'show keymaps' to see the existing keymaps.\n"
 	      "Key sequences may be things like M-C-t or NPAGE.\n"),
-
-  OWLCMD_ARGS("style", owl_command_style, OWL_CTX_ANY,
-	      "creates a new style",
-	      "style <name> perl <function_name>",
-	      "Creates a new style for formatting messages.\n"
-	      "A style named <name> will be created that will\n"
-	      "format messages using the perl function <function_name>.\n\n"
-	      "SEE ALSO: show styles, view -s, filter -s\n"),
 
   OWLCMD_ARGS("zwrite", owl_command_zwrite, OWL_CTX_INTERACTIVE,
@@ -180,5 +172,5 @@
 	      "print <variable>\n"
 	      "print",
-	      "Print the value of the named variable.  If no arugments\n"
+	      "Print the value of the named variable.  If no arguments\n"
 	      "are used print the value of all variables.\n"),
 
@@ -599,5 +591,5 @@
 	      "smartnarrow [-i | --instance]",
 	      "If the curmsg is a personal message narrow\n"
-	      "   to the converstaion with that user.\n"
+	      "   to the conversation with that user.\n"
 	      "If the curmsg is a class message, instance foo, recip *\n"
 	      "   message, narrow to the class, inst.\n"
@@ -611,5 +603,5 @@
 	      "smartfilter [-i | --instance]",
 	      "If the curmsg is a personal message, the filter is\n"
-	      "   the converstaion with that user.\n"
+	      "   the conversation with that user.\n"
 	      "If the curmsg is a class message, instance foo, recip *\n"
 	      "   message, the filter is the class, inst.\n"
@@ -963,4 +955,6 @@
 		  "", ""),
 
+  OWLCMD_ALIAS("webzephyr", "zwrite daemon.webzephyr -c webzephyr -i"),
+
   /* This line MUST be last! */
   { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
@@ -1673,25 +1667,4 @@
   return NULL;
 }
-
-char *owl_command_style(int argc, char **argv, char *buff) {
-  owl_style *s;
-
-  /* Usage: style <name> perl <function> */
-  if (argc != 4 || strcmp(argv[2], "perl")) {
-    owl_function_makemsg("Usage: style <name> perl <function>");
-    return NULL;
-  }
-  if (!owl_perlconfig_is_function(argv[3])) {
-    owl_function_makemsg("Unable to create style '%s': no perl function '%s'",
-			 argv[1], argv[3]);
-    return NULL;
-  }
-  s=owl_malloc(sizeof(owl_style));
-  owl_style_create_perl(s, argv[1], argv[3], NULL);
-  owl_global_add_style(&g, s);
-
-  return NULL;
-}
-
 
 void owl_command_quit()
Index: functions.c
===================================================================
--- functions.c	(revision 6b580b05f6e84a05297c835e3ff724e1e3187e1c)
+++ functions.c	(revision cdd3959ca8040d068d22c13fc707f1c7b9033bc7)
@@ -258,5 +258,5 @@
   ret=owl_zwrite_create_from_line(&z, line);
   if (ret) {
-    owl_function_error("Error in zwrite arugments");
+    owl_function_error("Error in zwrite arguments");
     owl_zwrite_free(&z);
     return;
@@ -1925,5 +1925,5 @@
   owl_fmtext_append_normal(&fm, "\n");
 
-  owl_fmtext_append_normal(&fm, "  Startup Arugments: ");
+  owl_fmtext_append_normal(&fm, "  Startup Arguments: ");
   owl_fmtext_append_normal(&fm, owl_global_get_startupargs(&g));
   owl_fmtext_append_normal(&fm, "\n");
Index: global.c
===================================================================
--- global.c	(revision 054894e40925e613243a601d425b9d839c5e4910)
+++ global.c	(revision 8aa83ea376134255b914cca14465792288afcf9f)
@@ -453,4 +453,5 @@
   sepbar(NULL);
   owl_editwin_redisplay(&(g->tw), 0);
+  owl_function_full_redisplay(&g);
 
   /* TODO: this should handle other forms of popwins */
Index: keys.c
===================================================================
--- keys.c	(revision a6a4155377feb38fe96441b8929855698f9e9d03)
+++ keys.c	(revision 3004c9f7ea88e3888e2d6a71cbf552f9f9f84afb)
@@ -230,9 +230,13 @@
 
   BIND_CMD("LEFT",   "recv:shiftleft", "");
+  BIND_CMD("M-[ D",  "recv:shiftleft", "");
   BIND_CMD("RIGHT",  "recv:shiftright","");
+  BIND_CMD("M-[ C",  "recv:shiftleft", "");
   BIND_CMD("DOWN",   "recv:next",      "");
   BIND_CMD("C-n",    "recv:next",      "");
+  BIND_CMD("M-[ B",  "recv:next",      "");
   BIND_CMD("M-C-n",  "recv:next --smart-filter", "move to next message matching the current one"); 
   BIND_CMD("UP",     "recv:prev",      "");
+  BIND_CMD("M-[ A",  "recv:prev",      "");
   BIND_CMD("n",      "recv:next-notdel", "");
   BIND_CMD("p",      "recv:prev-notdel", "");
@@ -281,4 +285,6 @@
   BIND_CMD("w",   "openurl",          "open a URL using a webbrowser");
 
+  BIND_CMD("W",   "start-command webzephyr ", "start a webzephyr command");
+
   BIND_CMD("C-c",  "",                "no effect in this mode");
   BIND_CMD("C-g",  "",                "no effect in this mode");
Index: owl.c
===================================================================
--- owl.c	(revision 4cc0ee0b06df6e350c5c55723f86064f0f994bd9)
+++ owl.c	(revision 52f8dd6f954e971462a0a3fedc3550d1d0060e91)
@@ -274,11 +274,4 @@
   }
 
-  /* setup the built-in styles */
-  owl_function_debugmsg("startup: creating built-in styles");
-
-  s=owl_malloc(sizeof(owl_style));
-  owl_style_create_internal(s, "basic", &owl_stylefunc_basic, "Basic message formatting.");
-  owl_global_add_style(&g, s);
-
   /* setup the default filters */
   /* the personal filter will need to change again when AIM chat's are
@@ -409,10 +402,6 @@
   if (0 != strcmp(owl_global_get_default_style(&g), "__unspecified__")) {
     /* the style was set by the user: leave it alone */
-  } else if (owl_global_is_config_format(&g)) {
-    owl_global_set_default_style(&g, "perl");
-  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
+  } else {
     owl_global_set_default_style(&g, "default");
-  } else {
-    owl_global_set_default_style(&g, "basic");
   }
 
@@ -436,4 +425,9 @@
   nexttime=time(NULL);
 
+#ifdef HAVE_LIBZEPHYR
+  /* Check for any zephyrs that have come in while we've done init. */
+  owl_zephyr_process_events();
+#endif
+  
   owl_function_debugmsg("startup: entering main loop");
   /* main loop */
@@ -595,5 +589,5 @@
   if(owl_message_is_direction_in(m)) {
     /* let perl know about it*/
-    owl_perlconfig_getmsg(m, 0, NULL);
+    owl_perlconfig_getmsg(m, NULL);
 
     /* do we need to autoreply? */
Index: owl.h
===================================================================
--- owl.h	(revision 9c7a701363179369d764454b0d99e559ab89ed9e)
+++ owl.h	(revision 120291c1279afc08f2efbc7c70dd1e069109c9c3)
@@ -70,4 +70,5 @@
 #define HAS_BOOL
 #include <perl.h>
+#include "owl_perl.h"
 #undef logout
 #include "XSUB.h"
@@ -162,7 +163,4 @@
 #define OWL_SCROLLMODE_PAGED       4
 #define OWL_SCROLLMODE_PAGEDCENTER 5
-
-#define OWL_STYLE_TYPE_INTERNAL  0
-#define OWL_STYLE_TYPE_PERL      1
 
 #define OWL_TAB               3  /* This *HAS* to be the size of TABSTR below */
@@ -386,8 +384,5 @@
 typedef struct _owl_style {
   char *name;
-  char *description;
-  int type;
-  char *perlfuncname;
-  void (*formatfunc) (owl_fmtext *fm, owl_message *m);
+  SV *perlobj;
 } owl_style;
 
Index: owl_perl.h
===================================================================
--- owl_perl.h	(revision 120291c1279afc08f2efbc7c70dd1e069109c9c3)
+++ owl_perl.h	(revision 120291c1279afc08f2efbc7c70dd1e069109c9c3)
@@ -0,0 +1,55 @@
+#ifndef INC_OWL_PERL_H
+#define INC_OWL_PERL_H
+
+#define OWL_PERL_VOID_CALL (void)POPs;
+
+/*
+ * This macro defines a convenience wrapper around the boilerplate of
+ * calling a method on a perl object (SV*) from C.
+ *
+ * Arguments are
+ * * obj    - the SV* to call the method on
+ * * meth   - a char* method name
+ * * args   - a code block responsible for pushing args (other than the object)
+ * * err    - a string with a %s format specifier to log in case of error
+ * * fatalp - if true, perl errors terminate barnowl
+ * * ret    - a code block executed if the call succeeded
+ *
+ * See also: `perldoc perlcall', `perldoc perlapi'
+ */
+#define OWL_PERL_CALL_METHOD(obj, meth, args, err, fatalp, ret) { \
+    int count; \
+    dSP; \
+    ENTER; \
+    SAVETMPS; \
+    PUSHMARK(SP); \
+    XPUSHs(obj); \
+    {args} \
+    PUTBACK; \
+    \
+    count = call_method(meth, G_SCALAR|G_EVAL); \
+    \
+    SPAGAIN; \
+    \
+    if(count != 1) { \
+      fprintf(stderr, "perl returned wrong count: %d\n", count); \
+      abort();                                                   \
+    } \
+    if (SvTRUE(ERRSV)) { \
+      if(fatalp) { \
+        printf(err, SvPV_nolen(ERRSV)); \
+        exit(-1); \
+      } else { \
+        owl_function_error(err, SvPV_nolen(ERRSV)); \
+        (void)POPs; \
+        sv_setsv(ERRSV, &PL_sv_undef); \
+      } \
+    } else { \
+      ret; \
+    } \
+    PUTBACK; \
+    FREETMPS; \
+    LEAVE; \
+}
+
+#endif //INC_PERL_PERL_H
Index: perl/lib/BarnOwl/ModuleLoader.pm
===================================================================
--- perl/lib/BarnOwl/ModuleLoader.pm	(revision e005862ff892edaf5f690d38b843fce5dcc4fdbb)
+++ perl/lib/BarnOwl/ModuleLoader.pm	(revision 965e14de7fdd8473abb3847fe7f44be48833964e)
@@ -40,5 +40,5 @@
         if(!defined eval "use BarnOwl::Module::$class") {
             # BarnOwl::error("Unable to load module $class: $!") if $!;
-            BarnOwl::error("Unable to load module $class: $@") if $@;
+            BarnOwl::error("Unable to load module $class: \n$@\n") if $@;
         }
     }
Index: perl/modules/IRC/lib/BarnOwl/Module/IRC.pm
===================================================================
--- perl/modules/IRC/lib/BarnOwl/Module/IRC.pm	(revision 9c7a701363179369d764454b0d99e559ab89ed9e)
+++ perl/modules/IRC/lib/BarnOwl/Module/IRC.pm	(revision 919535f023efc9441b94bc25939b3d170bd322d6)
@@ -199,5 +199,5 @@
         process_msg($conn, $to, join(" ", @_));
     } else {
-        BarnOwl::start_edit_win("/msg $to -a " . $conn->alias, sub {process_msg($conn, $to, @_)});
+        BarnOwl::start_edit_win("/msg -a " . $conn->alias . " $to", sub {process_msg($conn, $to, @_)});
     }
 }
@@ -209,5 +209,10 @@
     # Strip whitespace. In the future -- send one message/line?
     $body =~ tr/\n\r/  /;
-    $conn->conn->privmsg($to, $body);
+    if ($body =~ /^\/me (.*)/) {
+        $conn->conn->me($to, $1);
+        $body = BarnOwl::Style::boldify($conn->nick.' '.$1);
+    } else {
+        $conn->conn->privmsg($to, $body);
+    }
     my $msg = BarnOwl::Message->new(
         type        => 'IRC',
@@ -220,6 +225,6 @@
         is_private($to) ?
           (isprivate  => 'true') : (channel => $to),
-        replycmd    => "irc-msg $to",
-        replysendercmd => "irc-msg $to"
+        replycmd    => "irc-msg -a " . $conn->alias . " $to",
+        replysendercmd => "irc-msg -a " . $conn->alias . " $to"
        );
     BarnOwl::queue_message($msg);
Index: perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm
===================================================================
--- perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm	(revision 661d2eb492f68fa8ed0a89130ecd04e0148307e9)
+++ perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm	(revision 8faab0c804c9d8367f230dba7c79efa9c7b62cd6)
@@ -108,7 +108,7 @@
         is_private($recipient) ?
           (isprivate  => 'true') : (channel => $recipient),
-        replycmd    => 'irc-msg ' .
+        replycmd    => 'irc-msg -a ' . $self->alias . ' ' .
             (is_private($recipient) ? $evt->nick : $recipient),
-        replysendercmd => 'irc-msg ' . $evt->nick
+        replysendercmd => 'irc-msg -a ' . $self->alias . ' ' . $evt->nick
        );
 
@@ -158,4 +158,6 @@
         loginout   => 'login',
         channel    => $evt->to,
+        replycmd => 'irc-msg -a ' . $self->alias . ' ' . $evt->nick,
+        replysendercmd => 'irc-msg -a ' . $self->alias . ' ' . $evt->nick
         );
     BarnOwl::queue_message($msg);
@@ -167,4 +169,6 @@
         loginout   => 'logout',
         channel    => $evt->to,
+        replycmd => 'irc-msg -a ' . $self->alias . ' ' . $evt->nick,
+        replysendercmd => 'irc-msg -a ' . $self->alias . ' ' . $evt->nick
         );
     BarnOwl::queue_message($msg);
Index: perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm
===================================================================
--- perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm	(revision 6b580b05f6e84a05297c835e3ff724e1e3187e1c)
+++ perl/modules/Jabber/lib/BarnOwl/Module/Jabber.pm	(revision b72a352f6f714ab01a0c4769e8db5761af065e69)
@@ -25,4 +25,5 @@
 use Net::DNS;
 use Getopt::Long;
+Getopt::Long::Configure(qw(no_getopt_compat prefix_pattern=-|--));
 
 use utf8;
@@ -479,5 +480,5 @@
         'account=s' => \$from,
         'id=s'     =>  \$jwrite_sid,
-    );
+    ) or die("Usage: jwrite JID [-t thread] [-s 'subject'] [-a account]\n");
     $jwrite_type = 'groupchat' if $gc;
 
@@ -570,5 +571,5 @@
 
         my $getopt = Getopt::Long::Parser->new;
-        $getopt->configure('pass_through');
+        $getopt->configure('pass_through', 'no_getopt_compat');
         $getopt->getoptions( 'account=s' => \$jid );
         $jid ||= defaultJID();
@@ -734,5 +735,5 @@
         my $purgeGroups;
         my $getopt = Getopt::Long::Parser->new;
-        $getopt->configure('pass_through');
+        $getopt->configure('pass_through', 'no_getopt_compat');
         $getopt->getoptions(
             'account=s' => \$jid,
Index: perl/modules/Jabber/lib/Net/Jabber/Data.pm
===================================================================
--- perl/modules/Jabber/lib/Net/Jabber/Data.pm	(revision c2bed5539d456612d69de33e1dacc3afe5f70395)
+++ perl/modules/Jabber/lib/Net/Jabber/Data.pm	(revision cdd3959ca8040d068d22c13fc707f1c7b9033bc7)
@@ -120,5 +120,5 @@
 to go into full detail on each of these functions.  Rather I will
 present the functions in a list with a type in the first column to
-show what they return, or take as arugments.  Here is the list of
+show what they return, or take as arguments.  Here is the list of
 types I will use:
 
Index: perl/modules/Jabber/lib/Net/Jabber/Protocol.pm
===================================================================
--- perl/modules/Jabber/lib/Net/Jabber/Protocol.pm	(revision c2bed5539d456612d69de33e1dacc3afe5f70395)
+++ perl/modules/Jabber/lib/Net/Jabber/Protocol.pm	(revision cdd3959ca8040d068d22c13fc707f1c7b9033bc7)
@@ -940,5 +940,5 @@
         if (!exists($funcHash{set}) && exists($funcHash{get}))
         {
-            croak("The DefineNamespace arugments have changed, and I cannot determine the\nnew values automatically for name($name).  Please read the man page\nfor Net::Jabber::Namespaces.  I apologize for this incompatability.\n");
+            croak("The DefineNamespace arguments have changed, and I cannot determine the\nnew values automatically for name($name).  Please read the man page\nfor Net::Jabber::Namespaces.  I apologize for this incompatability.\n");
         }
 
Index: perlconfig.c
===================================================================
--- perlconfig.c	(revision 9c7a701363179369d764454b0d99e559ab89ed9e)
+++ perlconfig.c	(revision b67ab6b90002b0f2ff52289b0318415bd73cace9)
@@ -411,32 +411,12 @@
 }
 
-char *owl_perlconfig_getmsg(owl_message *m, int mode, char *subname)
-{ 
-  /* if mode==1 we are doing message formatting.  The returned
-   * formatted message needs to be freed by the caller.
-   *
-   * if mode==0 we are just doing the message-has-been-received
-   * thing.
-   */
-  if (!owl_global_have_config(&g)) return(NULL);
-  
-  /* run the procedure corresponding to the mode */
-  if (mode==1) {
-    char *ret = NULL;
-    ret = owl_perlconfig_call_with_message(subname?subname
-					   :"BarnOwl::_format_msg_legacy_wrap", m);
-    if (!ret) {
-      ret = owl_sprintf("@b([Perl Message Formatting Failed!])\n");
-    } 
-    return ret;
-  } else {
-    char *ptr = NULL;
-    if (owl_perlconfig_is_function("BarnOwl::Hooks::_receive_msg")) {
-      ptr = owl_perlconfig_call_with_message(subname?subname
-				       :"BarnOwl::_receive_msg_legacy_wrap", m);
-    }
-    if (ptr) owl_free(ptr);
-    return(NULL);
-  }
+void owl_perlconfig_getmsg(owl_message *m, char *subname)
+{
+  char *ptr = NULL;
+  if (owl_perlconfig_is_function("BarnOwl::Hooks::_receive_msg")) {
+    ptr = owl_perlconfig_call_with_message(subname?subname
+                                           :"BarnOwl::_receive_msg_legacy_wrap", m);
+  }
+  if (ptr) owl_free(ptr);
 }
 
Index: perlglue.xs
===================================================================
--- perlglue.xs	(revision 9c7a701363179369d764454b0d99e559ab89ed9e)
+++ perlglue.xs	(revision b67ab6b90002b0f2ff52289b0318415bd73cace9)
@@ -256,16 +256,13 @@
 
 void
-_create_style(name, function, description)
+create_style(name, object)
      char *name
-     char *function
-     char *description
+     SV  *object
      PREINIT:
-		/* This is to allow us to bootstrap the default style before the
-		command architecture has been initialized */
 		owl_style *s;
      CODE:
 	{
 		s = owl_malloc(sizeof(owl_style));
-		owl_style_create_perl(s, name, function, description);
+		owl_style_create_perl(s, name, object);
 		owl_global_add_style(&g, s);
 	}
Index: perlwrap.pm
===================================================================
--- perlwrap.pm	(revision 9815e2e0d63da9ec80cf2cd49d34c9ae896f1967)
+++ perlwrap.pm	(revision 811ad935eaaf767e7199aa16b2b23047e832e5f5)
@@ -153,11 +153,4 @@
 }
 $configfile ||= $ENV{HOME}."/.owlconf";
-
-# populate global variable space for legacy owlconf files
-sub _format_msg_legacy_wrap {
-    my ($m) = @_;
-    $m->legacy_populate_global();
-    return &BarnOwl::format_msg($m);
-}
 
 # populate global variable space for legacy owlconf files
@@ -692,4 +685,18 @@
 # Internal startup/shutdown routines called by the C code
 
+sub _load_perl_commands {
+    # Load builtin perl commands
+    BarnOwl::new_command(style => \&BarnOwl::Style::style_command,
+                       {
+                           summary => "creates a new style",
+                           usage   => "style <name> perl <function_name>",
+                           description =>
+                           "A style named <name> will be created that will\n" .
+                           "format messages using the perl function <function_name>.\n\n" .
+                           "SEE ALSO: show styles, view -s, filter -s\n\n" .
+                           "DEPRECATED in favor of BarnOwl::create_style(NAME, OBJECT)",
+                          });
+}
+
 sub _load_owlconf {
     # load the config  file
@@ -702,8 +709,10 @@
         if(*BarnOwl::format_msg{CODE}) {
             # if the config defines a legacy formatting function, add 'perl' as a style 
-            BarnOwl::_create_style("perl", "BarnOwl::_format_msg_legacy_wrap",
-                                   "User-defined perl style that calls BarnOwl::format_msg"
-                                   . " with legacy global variable support");
-            BarnOwl::set("-q default_style perl");
+            BarnOwl::create_style("perl", BarnOwl::Style::Legacy->new(
+                "BarnOwl::format_msg",
+                "User-defined perl style that calls BarnOwl::format_msg"
+                . " with legacy global variable support",
+                1));
+             BarnOwl::set("-q default_style perl");
         }
     }
@@ -715,4 +724,5 @@
 
 sub _startup {
+    _load_perl_commands();
     _load_owlconf();
 
@@ -763,18 +773,30 @@
 sub format_message($)
 {
-    my $m = shift;
+    my $self = shift;
+    my $m    = shift;
+    my $fmt;
 
     if ( $m->is_loginout) {
-        return format_login($m);
+        $fmt = $self->format_login($m);
     } elsif($m->is_ping && $m->is_personal) {
-        return ( "\@b(PING) from \@b(" . $m->pretty_sender . ")\n" );
+        $fmt = $self->format_ping($m);
     } elsif($m->is_admin) {
-        return "\@bold(OWL ADMIN)\n" . indentBody($m);
+        $fmt = $self->format_admin($m);
     } else {
-        return format_chat($m);
-    }
-}
-
-BarnOwl::_create_style("default", "BarnOwl::Style::Default::format_message", "Default style");
+        $fmt = $self->format_chat($m);
+    }
+    $fmt = BarnOwl::Style::boldify($fmt) if $self->should_bold($m);
+    return $fmt;
+}
+
+sub should_bold {
+    my $self = shift;
+    my $m = shift;
+    return $m->is_personal && $m->direction eq "in";
+}
+
+sub description {"Default style";}
+
+BarnOwl::create_style("default", "BarnOwl::Style::Default");
 
 ################################################################################
@@ -787,4 +809,5 @@
 
 sub format_login($) {
+    my $self = shift;
     my $m = shift;
     return sprintf(
@@ -798,5 +821,25 @@
 }
 
+sub format_ping {
+    my $self = shift;
+    my $m = shift;
+    return "\@b(PING) from \@b(" . $m->pretty_sender . ")\n";
+}
+
+sub format_admin {
+    my $self = shift;
+    my $m = shift;
+    return "\@bold(OWL ADMIN)\n" . $self->indent_body($m);
+}
+
 sub format_chat($) {
+    my $self = shift;
+    my $m = shift;
+    my $header = $self->chat_header($m);
+    return $header . "\n". $self->indent_body($m);
+}
+
+sub chat_header {
+    my $self = shift;
     my $m = shift;
     my $header;
@@ -819,17 +862,19 @@
     }
     $header .= "  " . time_hhmm($m);
+    $header .= $self->format_sender($m);
+    return $header;
+}
+
+sub format_sender {
+    my $self = shift;
+    my $m = shift;
     my $sender = $m->long_sender;
     $sender =~ s/\n.*$//s;
-    $header .= " " x (4 - ((length $header) % 4));
-    $header .= "(" . $sender . '@color[default]' . ")";
-    my $message = $header . "\n". indentBody($m);
-    if($m->is_personal && $m->direction eq "in") {
-        $message = BarnOwl::Style::boldify($message);
-    }
-    return $message;
-}
-
-sub indentBody($)
+    return "  (" . $sender . '@color[default]' . ")";
+}
+
+sub indent_body($)
 {
+    my $self = shift;
     my $m = shift;
 
@@ -846,34 +891,25 @@
 }
 
+package BarnOwl::Style::Basic;
+our @ISA=qw(BarnOwl::Style::Default);
+
+sub description {"Compatability alias for the default style";}
+
+BarnOwl::create_style("basic", "BarnOwl::Style::Basic");
+
 package BarnOwl::Style::OneLine;
+# Inherit format_message to dispatch
+our @ISA = qw(BarnOwl::Style::Default);
+
+use constant BASE_FORMAT => '%s %-13.13s %-11.11s %-12.12s ';
+
+sub description {"Formats for one-line-per-message"}
+
+BarnOwl::create_style("oneline", "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 $self = shift;
   my $m = shift;
   return sprintf(
@@ -898,4 +934,5 @@
 sub format_chat($)
 {
+  my $self = shift;
   my $m = shift;
   my $dir = lc($m->{direction});
@@ -911,19 +948,19 @@
   if ($m->is_personal) {
     $line= sprintf(BASE_FORMAT,
-		   $dirsym,
-		   $m->type,
-		   '',
-		   ($dir eq 'out'
-		      ? $m->pretty_recipient
-		      : $m->pretty_sender));
+                   $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));
+                    $dirsym,
+                    $m->context,
+                    $m->subcontext,
+                    ($dir eq 'out'
+                     ? $m->pretty_recipient
+                     : $m->pretty_sender));
   }
 
@@ -931,14 +968,13 @@
   $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($)
+# Format owl admin messages
+sub format_admin($)
 {
+  my $self = shift;
   my $m = shift;
-  my $type = uc($m->{type});
-  my $line = sprintf(BASE_FORMAT, '<', $type, '', '');
+  my $line = sprintf(BASE_FORMAT, '<', 'ADMIN', '', '');
   my $body = $m->{body};
   $body =~ tr/\n/ /;
@@ -968,4 +1004,49 @@
 }
 
+sub style_command {
+    my $command = shift;
+    if(scalar @_ != 3 || $_[1] ne 'perl') {
+        die("Usage: style <name> perl <function>\n");
+    }
+    my $name = shift;
+    my $perl = shift;
+    my $fn   = shift;
+    {
+        no strict 'refs';
+        unless(*{$fn}{CODE}) {
+            die("Unable to create style '$name': no perl function '$fn'\n");
+        }
+    }
+    BarnOwl::create_style($name, BarnOwl::Style::Legacy->new($fn));
+}
+
+package BarnOwl::Style::Legacy;
+
+sub new {
+    my $class = shift;
+    my $func  = shift;
+    my $desc  = shift;
+    my $useglobals = shift;
+    $useglobals = 0 unless defined($useglobals);
+    return bless {function    => $func,
+                  description => $desc,
+                  useglobals  => $useglobals}, $class;
+}
+
+sub description {
+    my $self = shift;
+    return $self->{description} ||
+    ("User-defined perl style that calls " . $self->{function});
+};
+
+sub format_message {
+    my $self = shift;
+    if($self->{useglobals}) {
+        $_[0]->legacy_populate_global();
+    }
+    no strict 'refs';
+    goto \&{$self->{function}};
+}
+
 
 # switch to package main when we're done
Index: style.c
===================================================================
--- style.c	(revision 5a9f6fe47907e20e155786f4bd2ccfc8cb0b0782)
+++ style.c	(revision 864ed359c1c6fbc341ca8d3a273cb7c2ae4e0875)
@@ -1,31 +1,11 @@
+#define OWL_PERL
 #include "owl.h"
 
 static const char fileIdent[] = "$Id$";
 
-void owl_style_create_internal(owl_style *s, char *name, void (*formatfunc) (owl_fmtext *fm, owl_message *m), char *description)
+void owl_style_create_perl(owl_style *s, char *name, SV *obj)
 {
-  s->type=OWL_STYLE_TYPE_INTERNAL;
   s->name=owl_strdup(name);
-  if (description) {
-    s->description=owl_strdup(description);
-  } else {
-    s->description=owl_sprintf("Owl internal style %s", name);
-  }
-  s->perlfuncname=NULL;
-  s->formatfunc=formatfunc;
-}
-
-void owl_style_create_perl(owl_style *s, char *name, char *perlfuncname, char *description)
-{
-  s->type=OWL_STYLE_TYPE_PERL;
-  s->name=owl_strdup(name);
-  s->perlfuncname=owl_strdup(perlfuncname);
-  if (description) {
-    s->description=owl_strdup(description);
-  } else {
-    s->description=owl_sprintf("User-defined perl style that calls %s", 
-			       perlfuncname);
-  }
-  s->formatfunc=NULL;
+  s->perlobj = SvREFCNT_inc(obj);
 }
 
@@ -43,5 +23,17 @@
 char *owl_style_get_description(owl_style *s)
 {
-  return(s->description);
+  SV *sv = NULL;
+  OWL_PERL_CALL_METHOD(s->perlobj,
+                       "description",
+                       /* no args */,
+                       "Error in style_get_description: %s",
+                       0,
+                       sv = SvREFCNT_inc(POPs);
+                       );
+  if(sv) {
+    return SvPV_nolen(sv_2mortal(sv));
+  } else {
+    return "[error getting description]";
+  }
 }
 
@@ -51,46 +43,46 @@
 void owl_style_get_formattext(owl_style *s, owl_fmtext *fm, owl_message *m)
 {
-  if (s->type==OWL_STYLE_TYPE_INTERNAL) {
-    (* s->formatfunc)(fm, m);
-  } else if (s->type==OWL_STYLE_TYPE_PERL) {
-    char *body, *indent;
-    int curlen;
+  char *body, *indent;
+  int curlen;
 
-    /* run the perl function */
-    body=owl_perlconfig_getmsg(m, 1, s->perlfuncname);
-    if (!strcmp(body, "")) {
-      owl_free(body);
-      body=owl_strdup("<unformatted message>");
-    }
-    
-    /* indent and ensure ends with a newline */
-    indent=owl_malloc(strlen(body)+(owl_text_num_lines(body))*OWL_TAB+10);
-    owl_text_indent(indent, body, OWL_TAB);
-    curlen = strlen(indent);
-    if (curlen==0 || indent[curlen-1] != '\n') {
-      indent[curlen] = '\n';
-      indent[curlen+1] = '\0';
-    }
+  SV *sv = NULL;
+  
+  /* Call the perl object */
+  OWL_PERL_CALL_METHOD(s->perlobj,
+                       "format_message",
+                       XPUSHs(owl_perlconfig_message2hashref(m));,
+                       "Error in format_message: %s",
+                       0,
+                       sv = SvREFCNT_inc(POPs);
+                       );
 
-    /* fmtext_append.  This needs to change */
-    owl_fmtext_append_ztext(fm, indent);
-    
-    owl_free(indent);
-    owl_free(body);
+  if(sv) {
+    body = SvPV_nolen(sv);
+  } else {
+    body = "<unformatted message>";
   }
+
+  /* indent and ensure ends with a newline */
+  indent=owl_malloc(strlen(body)+(owl_text_num_lines(body))*OWL_TAB+10);
+  owl_text_indent(indent, body, OWL_TAB);
+  curlen = strlen(indent);
+  if (curlen==0 || indent[curlen-1] != '\n') {
+    indent[curlen] = '\n';
+    indent[curlen+1] = '\0';
+  }
+
+  /* fmtext_append.  This needs to change */
+  owl_fmtext_append_ztext(fm, indent);
+
+  owl_free(indent);
+  if(sv)
+    SvREFCNT_dec(body);
 }
 
 int owl_style_validate(owl_style *s) {
-  if (!s) {
-    return -1;
-  } else if (s->type==OWL_STYLE_TYPE_INTERNAL) {
-    return 0;
-  } else if (s->type==OWL_STYLE_TYPE_PERL 
-	     && s->perlfuncname 
-	     && owl_perlconfig_is_function(s->perlfuncname)) {
-    return 0;
-  } else {
+  if (!s || !s->perlobj || !SvOK(s->perlobj)) {
     return -1;
   }
+  return 0;
 }
 
@@ -98,7 +90,4 @@
 {
   if (s->name) owl_free(s->name);
-  if (s->description) owl_free(s->description);
-  if (s->type==OWL_STYLE_TYPE_PERL && s->perlfuncname) {
-    owl_free(s->perlfuncname);
-  }
+  SvREFCNT_dec(s->perlobj);
 }
Index: ylefunc.c
===================================================================
--- stylefunc.c	(revision f2d72128d54fe0a3466422505e2ae01e3b137498)
+++ 	(revision )
@@ -1,221 +1,0 @@
-#include "owl.h"
-
-static const char fileIdent[] = "$Id$";
-
-/* In all of these functions, 'fm' is expected to already be
- * initialized.
- */
-
-void owl_style_basic_format_body(owl_fmtext *fm, owl_message *m) {
-  char *indent, *body;
-  owl_filter *f;
-  int wrap = 0;
-
-  /* get the body */
-  body=owl_strdup(owl_message_get_body(m));
-
-  f = owl_global_get_filter(&g, "wordwrap");
-  if(f && owl_filter_message_match(f, m)) 
-    wrap = 1;
-
-  if(wrap) {
-    int cols, i, width, word;
-    char *tab, *tok, *ws = " \t\n\r";
-    cols = owl_global_get_cols(&g) - OWL_MSGTAB - 1;
-
-    tab = owl_malloc(OWL_MSGTAB+1);
-    for(i = 0; i < OWL_MSGTAB; i++) {
-      tab[i] = ' ';
-    }
-    tab[OWL_MSGTAB] = 0;
-
-    tok = strtok(body, ws);
-    tab[OWL_MSGTAB-1] = 0;
-    owl_fmtext_append_normal(fm, tab);
-    tab[OWL_MSGTAB-1] = ' ';
-    width = 0;
-
-    while(tok) {
-      word = strlen(tok);
-      if(word + width + 1 < cols) {
-        owl_fmtext_append_normal(fm, " ");
-        owl_fmtext_append_normal(fm, tok);
-        width += word + 1;
-      } else {
-        owl_fmtext_append_normal(fm, "\n");
-        owl_fmtext_append_normal(fm, tab);
-        owl_fmtext_append_normal(fm, tok);
-        width = word;
-      }
-      tok = strtok(NULL, ws);
-    }
-    owl_fmtext_append_normal(fm, "\n");
-
-    owl_free(tab);
-  } else {
-    /* do the indenting into indent */
-    indent=owl_malloc(strlen(body)+owl_text_num_lines(body)*OWL_MSGTAB+10);
-    owl_text_indent(indent, body, OWL_MSGTAB);
-    owl_fmtext_append_ztext(fm, indent);
-    if(body[strlen(body)-1] != '\n')
-      owl_fmtext_append_ztext(fm, "\n");
-    owl_free(indent);
-  }
-
-  owl_free(body);
-}
- 
-void owl_stylefunc_basic(owl_fmtext *fm, owl_message *m)
-{
-#ifdef HAVE_LIBZEPHYR
-  char *ptr, *zsigbuff, frombuff[LINE];
-  ZNotice_t *n;
-#endif
-
-  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
-#ifdef HAVE_LIBZEPHYR
-    n=owl_message_get_notice(m);
-  
-    /* edit the from addr for printing */
-    strcpy(frombuff, owl_message_get_sender(m));
-    ptr=strchr(frombuff, '@');
-    if (ptr && !strncmp(ptr+1, owl_zephyr_get_realm(), strlen(owl_zephyr_get_realm()))) {
-      *ptr='\0';
-    }
-    
-    /* set the message for printing */
-    owl_fmtext_append_normal(fm, OWL_TABSTR);
-    
-    if (owl_message_is_ping(m)) {
-      owl_fmtext_append_bold(fm, "PING");
-      owl_fmtext_append_normal(fm, " from ");
-      owl_fmtext_append_bold(fm, frombuff);
-      owl_fmtext_append_normal(fm, "\n");
-    } else 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)) {
-	owl_fmtext_append_bold(fm, "LOGIN");
-      } else if (owl_message_is_logout(m)) {
-	owl_fmtext_append_bold(fm, "LOGOUT");
-      }
-      if (owl_message_is_pseudo(m)) {
-	owl_fmtext_append_bold(fm, " (PSEUDO)");
-      }
-      owl_fmtext_append_normal(fm, " for ");
-      ptr=short_zuser(owl_message_get_instance(m));
-      owl_fmtext_append_bold(fm, ptr);
-      owl_free(ptr);
-      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 {
-      owl_fmtext_append_normal(fm, "From: ");
-      if (strcasecmp(owl_message_get_class(m), "message")) {
-	owl_fmtext_append_normal(fm, "Class ");
-	owl_fmtext_append_normal(fm, owl_message_get_class(m));
-	owl_fmtext_append_normal(fm, " / Instance ");
-	owl_fmtext_append_normal(fm, owl_message_get_instance(m));
-	owl_fmtext_append_normal(fm, " / ");
-      }
-      owl_fmtext_append_normal(fm, frombuff);
-      if (strcasecmp(owl_message_get_realm(m), owl_zephyr_get_realm())) {
-	owl_fmtext_append_normal(fm, " {");
-	owl_fmtext_append_normal(fm, owl_message_get_realm(m));
-	owl_fmtext_append_normal(fm, "} ");
-      }
-      
-      /* stick on the zsig */
-      zsigbuff=owl_malloc(strlen(owl_message_get_zsig(m))+30);
-      owl_message_pretty_zsig(m, zsigbuff);
-      owl_fmtext_append_normal(fm, "    (");
-      owl_fmtext_append_ztext(fm, zsigbuff);
-      owl_fmtext_append_normal(fm, ")");
-      owl_fmtext_append_normal(fm, "\n");
-      owl_free(zsigbuff);
-      
-      /* then the indented message */
-      owl_style_basic_format_body(fm, m);
-      
-      /* make personal messages bold for smaat users */
-      if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
-	if (owl_message_is_personal(m)) {
-	  owl_fmtext_addattr(fm, OWL_FMTEXT_ATTR_BOLD);
-	}
-      }
-    }
-    
-#endif
-  } else if (owl_message_is_type_zephyr(m) && owl_message_is_direction_out(m)) {
-    char *zsigbuff, *foo;
-    owl_fmtext_append_normal(fm, OWL_TABSTR);
-    owl_fmtext_append_normal(fm, "To: ");
-    foo=short_zuser(owl_message_get_recipient(m));
-    owl_fmtext_append_normal(fm, foo);
-    owl_free(foo);
-    owl_fmtext_append_normal(fm, "  (Zsig: ");
-    
-    zsigbuff=owl_malloc(strlen(owl_message_get_zsig(m))+30);
-    owl_message_pretty_zsig(m, zsigbuff);
-    owl_fmtext_append_ztext(fm, zsigbuff);
-    owl_free(zsigbuff);
-    
-    owl_fmtext_append_normal(fm, ")");
-    owl_fmtext_append_normal(fm, "\n");
-    owl_style_basic_format_body(fm, m);
-  } else if (owl_message_is_type_aim(m)) {
-    if (owl_message_is_loginout(m)) {
-      owl_fmtext_append_normal(fm, OWL_TABSTR);
-      if (owl_message_is_login(m)) {
-	owl_fmtext_append_bold(fm, "AIM LOGIN");
-      } else {
-	owl_fmtext_append_bold(fm, "AIM LOGOUT");
-      }
-      owl_fmtext_append_normal(fm, " for ");
-      owl_fmtext_append_normal(fm, owl_message_get_sender(m));
-      owl_fmtext_append_normal(fm, "\n");
-    } else if (owl_message_is_direction_in(m)) {
-      owl_fmtext_append_bold(fm, OWL_TABSTR);
-      owl_fmtext_append_bold(fm, "AIM from ");
-      owl_fmtext_append_bold(fm, owl_message_get_sender(m));
-      owl_fmtext_append_bold(fm, "\n");
-      owl_style_basic_format_body(fm, m);
-    } else if (owl_message_is_direction_out(m)) {
-      owl_fmtext_append_normal(fm, OWL_TABSTR);
-      owl_fmtext_append_normal(fm, "AIM sent to ");
-      owl_fmtext_append_normal(fm, owl_message_get_recipient(m));
-      owl_fmtext_append_normal(fm, "\n");
-      owl_style_basic_format_body(fm, m);
-    }
-  } else if (owl_message_is_type_admin(m)) {
-    char *text, *header;
-    
-    text=owl_message_get_body(m);
-    header=owl_message_get_attribute_value(m, "adminheader");
-
-    owl_fmtext_append_normal(fm, OWL_TABSTR);
-    owl_fmtext_append_bold(fm, "OWL ADMIN ");
-    owl_fmtext_append_ztext(fm, header);
-    owl_fmtext_append_normal(fm, "\n");
-    owl_style_basic_format_body(fm, m);
-  } else {
-    char *header;
-
-    header=owl_sprintf("%s from: %s to: %s",
-		       owl_message_get_type(m),
-		       owl_message_get_sender(m),
-		       owl_message_get_recipient(m));
-
-    owl_fmtext_append_normal(fm, OWL_TABSTR);
-    owl_fmtext_append_normal(fm, header);
-    owl_fmtext_append_normal(fm, "\n");
-    owl_style_basic_format_body(fm, m);
-    
-    owl_free(header);
-  }
-}
Index: svkversion
===================================================================
--- svkversion	(revision 95e60d6693398eccfa7b9f47040b0eb24e4accd7)
+++ svkversion	(revision 51f45d1f78677b5a52249457f10ef0021ee46220)
@@ -15,5 +15,9 @@
 $p ||= ".";
 
-my @lines = `svk info $p`;
+my @lines = `svk info $p 2>&1`;
+if($! || $lines[0] =~ "not a checkout path") {
+    print "exported$newline";
+    exit;
+}
 my @merged = grep {/^Merged From: /} @lines;
 
Index: variable.c
===================================================================
--- variable.c	(revision 247cbc94778c667e121bffe6507bcb993e0967f6)
+++ variable.c	(revision 52f8dd6f954e971462a0a3fedc3550d1d0060e91)
@@ -273,5 +273,4 @@
 		 "Some built-in styles include:\n"
 		 "   default  - the default owl formatting\n"
-		 "   basic    - simple formatting\n"
 		 "   oneline  - one line per-message\n"
 		 "   perl     - legacy perl interface\n"
