Index: ChangeLog
===================================================================
--- ChangeLog	(revision 687345590215e63bdcb0d5f5db2ae601600f0468)
+++ ChangeLog	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -1,3 +1,38 @@
 $Id$
+
+2.0.8-pre-2
+	New API for perl message formatting functions.  
+	        Legacy variables are still supported for owl::format_msg
+		and owl::receive_msg, but these functions are now also 
+		passed an owl::Message object which contains methods
+		for accessing the contents of the message.  See perlwrap.pm 
+		(and docs TBD) for the available methods.
+		*** WARNING:  The exact API for owl::Message has
+		*** not yet stabilized.
+	Added "style" command for creating new styles.
+	        Usage:  style <name> perl <function_name>
+	Added support for "show styles".  Changed global style table
+	        from list to dictionary.
+	Changed AIM password prompt from "Password:" to "AIM Password:".
+	Messages are reformatted after a window resize to allow styles
+	        to take into account the width of the window.
+	When perl throws an error, the message is put in the msgwin
+	        if possible.
+	Added perl functions for:	
+	        owl::getcurmsg() -- returns an owl::Message object for
+		                    the active message
+		                    in the current view.
+	        owl::getnumcols() -- returns the column width of the window
+		owl::zephyr_getrealm() -- returns the zephyr realm
+	        owl::zephyr_getsender() -- returns the zephyr sender
+	Made owl::COMMAND("foo"); be syntactic sugar for 
+	        owl::command("COMMAND foo");
+		*** Is this a good or bad idea? 
+		*** This feature may be taken out before release.
+	Added perlwrap.pm to contain perl code to be compiled into 
+	        the binary.  This is transformed into perlwrap.c by
+		encapsulate.pl.
+	Renamed readconfig.c to perlconfig.c and changed variables accordingly.
+	Minor bugfixes in cmd.c and commands.c
 
 2.0.8-pre-1
Index: Makefile.in
===================================================================
--- Makefile.in	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
+++ Makefile.in	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -20,8 +20,8 @@
 BASE_SRCS=list.c message.c mainwin.c popwin.c zephyr.c messagelist.c \
      commands.c global.c text.c fmtext.c editwin.c util.c logging.c \
-     readconfig.c keys.c functions.c zwrite.c viewwin.c help.c filter.c \
+     perlconfig.c keys.c functions.c zwrite.c viewwin.c help.c filter.c \
      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 buddylist.c timer.c style.c stylefunc.c
+     aim.c buddylist.c timer.c style.c stylefunc.c 
 OWL_SRC = owl.c
 TESTER_SRC = tester.c
@@ -29,5 +29,5 @@
 BASE_OBJS = $(BASE_SRCS:.c=.o)
 
-GEN_C = varstubs.c perlglue.c
+GEN_C = varstubs.c perlglue.c perlwrap.c
 GEN_H = owl_prototypes.h 
 GEN_O = $(GEN_C:.c=.o)
@@ -61,4 +61,7 @@
 varstubs.c: variable.c stubgen.pl
 	perl stubgen.pl > varstubs.c
+
+perlwrap.c: perlwrap.pm encapsulate.pl
+	perl encapsulate.pl perlwrap.pm owl_perlwrap_codebuff > perlwrap.c
 
 # Only move owl_prototypes.h into place if the new one is different
Index: cmd.c
===================================================================
--- cmd.c	(revision 1c7a4e01f25bb2fae17ec297a02deae08a0e92e6)
+++ cmd.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -96,8 +96,8 @@
   if (!templ->name) return(-1);
   cmd->name = owl_strdup(templ->name);
-  if (cmd->summary)     cmd->summary     = owl_strdup(templ->summary);
-  if (cmd->usage)       cmd->usage       = owl_strdup(templ->usage);
-  if (cmd->description) cmd->description = owl_strdup(templ->description);
-  if (cmd->cmd_aliased_to) cmd->cmd_aliased_to = owl_strdup(templ->cmd_aliased_to);
+  if (templ->summary)     cmd->summary     = owl_strdup(templ->summary);
+  if (templ->usage)       cmd->usage       = owl_strdup(templ->usage);
+  if (templ->description) cmd->description = owl_strdup(templ->description);
+  if (templ->cmd_aliased_to) cmd->cmd_aliased_to = owl_strdup(templ->cmd_aliased_to);
   return(0);
 }
Index: commands.c
===================================================================
--- commands.c	(revision 687345590215e63bdcb0d5f5db2ae601600f0468)
+++ commands.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -101,4 +101,12 @@
 	      "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,
@@ -567,4 +575,5 @@
 	      "show subscriptions\n"
 	      "show zpunts\n"
+	      "show styles\n"
 	      "show colors\n"
 	      "show terminal\n"
@@ -583,4 +592,6 @@
 	      "Show commands will list the names of all keymaps.\n"
 	      "Show command <command> will provide information about a command.\n\n"
+	      "Show styles will list the names of all styles available\n"
+	      "for formatting messages.\n\n"
 	      "Show variables will list the names of all variables.\n\n"
 	      "SEE ALSO: filter, view, alias, bindkey, help\n"),
@@ -1413,5 +1424,5 @@
 
   if (argc < 5 || strcmp(argv[3], "command")) {
-    owl_function_makemsg("Usage: bindkey <keymap> <binding> command <cmd>", argv[3], argc);
+    owl_function_makemsg("Usage: bindkey <keymap> <binding> command <cmd>");
     return NULL;
   }
@@ -1430,4 +1441,25 @@
   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()
@@ -1864,4 +1896,6 @@
   } else if (!strcmp(argv[1], "colors")) {
     owl_function_show_colors();
+  } else if (!strcmp(argv[1], "styles")) {
+    owl_function_show_styles();
   } else if (!strcmp(argv[1], "subs") || !strcmp(argv[1], "subscriptions")) {
     owl_function_getsubs();
@@ -2115,5 +2149,5 @@
   if (argc==2) {
     owl_global_set_buffercommand(&g, buff);
-    owl_function_start_password("Password: ");
+    owl_function_start_password("AIM Password: ");
     return(NULL);
   }
Index: encapsulate.pl
===================================================================
--- encapsulate.pl	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
+++ encapsulate.pl	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+#
+# $Id$
+#
+
+my $infile = $ARGV[0] or die "Usage: $0 infile structname";
+my $structname = $ARGV[1] or die "Usage: $0 infile structname";;
+open INF, "<$infile" or die "Unable to open $infile";
+
+print "/* This file was autogenerated from $infile.  DO NOT EDIT !!!! */\n\n";
+print "char *$structname = \n";
+for my $x (<INF>) {
+    chomp $x;
+    $x =~ s/\\/\\\\/g;
+    $x =~ s/"/\\"/g;
+    print qq(   "$x\\n"\n);
+}
+print "   ;\n";
+
+close INF;
Index: examples/owlconf.erik
===================================================================
--- examples/owlconf.erik	(revision 039213e3c8df62bb6cd227ac340655182b0c437f)
+++ examples/owlconf.erik	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -1,5 +1,5 @@
 ### The owlconf config file   -*- perl -*-  
 ###  $Id$
-
+###
 ### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!!
 ### This is an example file intended to demonstrate how to use 
@@ -9,5 +9,5 @@
 ### Don't blame me if anything in here ends up vaporizing your dog.
 ### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!!
-
+###
 ###
 ### This file is interpreted by the perl interpreter.
@@ -24,16 +24,11 @@
 ###     owl::startup()     run when owl first starts
 ###     owl::shutdown()    run when owl exits
-###     owl::format_msg()  run when a new message arrives, the return
-###                           value is used to display the message on the
-###                           screen
+###     owl::format_msg()  formats messages that are passed to it
 ###     owl::receive_msg() run when a message is received, and after
 ###	  	           it has been added to the message list
 ###
-###
-### The following variables will be set each time a message is recevied:
-###
-###     $owl::class, $owl::instance, $owl::recipient,
-###     $owl::sender, $owl::opcode, $owl::zsig,
-###     $owl::msg, $owl::time, $owl::host, @owl::fields, $owl::id
+### The format_msg and receive_msg functions are passed owl::Message objects.
+### The message attributes may be dereferenced with $m->attribute
+###
 ###    
 
@@ -46,4 +41,35 @@
 my @sepbartokens = ();
 
+# Map for mail messages from msg id to pop msg id
+my %mail_id_map = ();
+
+# (originally from jdaniel)
+sub mail_add_message ($) {
+    my ($m) = @_;
+    my $from = `from -t`;
+    # example value:
+    # You have 188 messages (667593 bytes) on PO11.MIT.EDU.
+    my ($msg_num) = $from =~ m/(\d+)/;
+    $mail_id_map{$m->id} = $msg_num;
+}
+
+
+sub mail_pop_curmsg () {
+    my $m = owl::getcurmsg();
+    if (!$m->is_mail || !defined $mail_id_map{$m->id}) {
+	&owl::command("pop-message");
+    } else {
+	&owl::command(sprintf 'pexec pop -request c -request "retr %d" -request q',
+		      $mail_id_map{$m->id});
+    }
+}
+
+sub zlocatesender {
+    my $m = owl::getcurmsg();
+    if ($m->{"type"} eq "zephyr") {
+	my $sender = $m->{"sender"};
+        owl::command("zlocate $sender");
+    }
+}
 
 # adds a sepbartoken and also updates the appendtosepbar variable
@@ -63,7 +89,9 @@
 }
 
+my $loopctr=0;
+
 # trims a sepbartoken from the list also updates the appendtosepbar variable
 sub sepbartokens_set {
-    owl::command(sprintf "set -q appendtosepbar \"%s\"", (join " ", @sepbartokens));
+    owl::command(sprintf "set -q appendtosepbar \"%s %s %s\"", (scalar localtime), (join " ", @sepbartokens));
 }
 
@@ -73,8 +101,8 @@
     if ($restoreview) {
         owl::command("view $restoreview");
-	$restoreview = undef;
-    } else {
-	$restoreview = $curview;
-	owl::command("smartnarrow");
+        $restoreview = undef;
+    } else {
+        $restoreview = $curview;
+        owl::command("smartnarrow");
     }
 }
@@ -91,52 +119,87 @@
     } else {
         owl::command("filter $smartfilt -c green");
-	$lastcolored = $smartfilt;
+        $lastcolored = $smartfilt;
+    }
+}
+
+# Load in things which don't belong in an owlconf 
+# that people might use as an example...
+sub personal_startup {
+    my $personalconf = $ENV{"HOME"}."/.owl/personalconf";
+    if (-f $personalconf) {
+	my $b = "";
+	open INB, $personalconf;
+	for (<INB>) { $b .= $_; }
+	close INB;
+	eval $b;
     }
 }
 
 sub owl::startup {
-    owl::command("set -q logging off");
-    owl::command("set -q zsigproc /home/nygren/bin/owlzsigs");
+    owl::command("set -q logging on");
+    owl::command("set -q logpath ~/.zlog/owl/personal");
+    owl::command("set -q classlogpath ~/.zlog/owl/class");
+    owl::command("set -q logging on");
     owl::command("set -q startuplogin off");
     owl::command("set -q shutdownlogout off");
     #owl::command("set personalbell on");
+    owl::command("set -q _burningears on");
     owl::command("set -q rxping on");
     owl::command("set -q typewinsize 5");
-    if ($ENV{"DISPLAY"} eq ":0") {
+    if ($ENV{"DISPLAY"} eq ":0.0") {
       owl::command("set -q webbrowser galeon");	
     }
-    owl::command("filter me recipient ".$ENV{"USER"});
-    owl::command("filter help class help");
-    owl::command("filter quiet not ( class ^greed|geek|help|login$ or instance white-magic )");    
+    owl::command("filter me recipient %me% or ( sender %me% and class message and instance personal ) or class mail or type aim");
+    owl::command("filter owl instance ^owl.*");
+
+    owl::command(q(alias finger pperl $x=owl::getcurmsg()->hostname; `finger \@$x`;));
+    owl::command("bindkey recv f command finger");
 
     owl::command("alias z zwrite");
-    owl::command("alias zc zwrite -c");
-
-    # Send zephyrs with "C-c C-c".  
-    # Note that this will cause "C-c" to not work...
-    owl::command("bindkey editmulti \"C-c C-c\" command editmulti:done");
-
-    # Make "d" ignore current movement direction
-    owl::command("bindkey recv d command ( delete --no-move ; next --skip-deleted )");
-
-    # Useful keys for reading and deleting by class/instance
+    owl::command("alias zw zwrite");
+    owl::command("alias v view");
+
+    owl::command("alias popmail perl mail_pop_curmsg();");
+
+    # toggle between a view and a smartnarrow with TAB
+    owl::command("alias swapview perl swapview();");
+    owl::command("bindkey recv C-i command swapview");
+
+    # color the current thread
+    owl::command("alias colorthread perl colorthread();");
+    owl::command("bindkey recv M-c command colorthread");
+
+    # zlocate current sender
+    owl::command("bindkey recv L command perl zlocatesender();");
+
+    # Declare styles
+    &owl::command("style vt     perl format_msg_vt");
+    &owl::command("style brief  perl format_msg_brief");
+    &owl::command("style custom perl format_msg_custom");
+    &owl::command("style debug  perl format_msg_debug");
+    &owl::command("set -q default_style custom");
+
+    # Change to different view styles
+    owl::command("bindkey recv \"C-s v\" command view -s vt");
+    owl::command("bindkey recv \"C-s c\" command view -s custom");
+    owl::command("bindkey recv \"C-s b\" command view -s brief");
+    owl::command("bindkey recv \"C-s d\" command view -s debug");
+    owl::command("bindkey recv \"C-s o\" command view -s standard");
+
+    # For fast-reading of zephyrs
     owl::command("bindkey recv M-k command ( smartnarrow ; delete view )");
     owl::command("bindkey recv M-l command ( expunge ; view all )");
     owl::command("bindkey recv M-K command ( smartnarrow ; delete view ; expunge ; view all )");
 
-    # Toggle between a view and a smartnarrow with TAB.
-    # Note that you probably want to use something other than TAB as 
-    # it will have another binding in a future version of owl.
-    owl::command("alias swapview perl swapview();");
-    owl::command("bindkey recv C-i command swapview");
-
-    # color the current thread
-    owl::command("alias colorthread perl colorthread();");
-    owl::command("bindkey recv M-c command colorthread");
-
-    # Make 'M-s' insert a <scritchscritchscritch> sequence with a random
-    # number of scritches.
-    owl::command(q(bindkey edit M-s command perl owl::command("edit:insert-text <".("scritch"x int(1+rand(5))).">")));
-
+    # Support for scroll mice
+    &owl::command("bindkey recv \"M-[ A\" command recv:prev");
+    &owl::command("bindkey recv \"M-[ B\" command recv:next");
+
+    # This overrides the default "M" keybinding
+    owl::command("bindkey recv M command popmail");
+
+    sepbartokens_add("...");
+
+    personal_startup();
 }
 
@@ -145,95 +208,272 @@
 }
 
+
+# run when a message is received, and after
+# it has been added to the message list.
+sub owl::receive_msg {
+    my ($m) = @_;
+    my ($out, $tmp);
+
+    if ($m->is_admin && !$m->is_outgoing) {
+	$m->delete();
+	return 1;
+    }
+
+    return 0 if (!$m->is_zephyr && !$m->is_aim);
+
+    my $sender = $m->pretty_sender;
+
+    if ($m->is_ping) {
+	sepbartokens_add(".$sender");
+        $m->delete();
+    } elsif ($m->is_loginout) {
+        $m->delete();
+	if ($m->is_login) {
+	    sepbartokens_add(">$sender");
+	    sepbartokens_trim("<$sender");
+	} elsif ($m->is_logout) {
+	    sepbartokens_add("<$sender");
+	    sepbartokens_trim(">$sender");
+	} 
+    } elsif ($m->is_mail) {
+	mail_add_message($m);
+        $m->delete();
+	sepbartokens_add("M");
+    }
+
+    if ($m->is_personal) {
+	sepbartokens_trim(".$sender");
+	sepbartokens_add(":$sender");
+    }
+
+    return 1;
+}
+
+sub indent4 {
+    my ($b) = @_;
+    $b=~s/^/    /g;
+    $b=~s/\n/\n    /g;    
+    return $b;
+}
+
 # run to format a message
-sub owl::format_msg {
-    my $out, $tmp;
-
-    $owl::sender=~s/\@ATHENA\.MIT\.EDU$//;
-    $owl::sender=~s/\@local-realm$//;
-
-    if (uc($owl::opcode) eq "PING") {
-	return("\@bold(PING) from \@bold($owl::sender)\n");
-    } elsif (uc($owl::class) eq "LOGIN") {
-	if (uc($owl::opcode) eq "USER_LOGIN") {
+sub format_msg_custom {
+    my ($m) = @_;
+    my ($out, $tmp);
+
+    if ($m->is_admin) {
+	$out = "\@bold([owl admin]) ".$m->header."\n";
+	$out.=indent4($m->body);
+	return $out."\n";
+    }
+
+    my $sender=$m->pretty_sender;
+
+    if (($m->is_aim or $m->is_zephyr) && $m->is_loginout) {
+
+	if ($m->is_login) {
 	    $out="\@bold(LOGIN)";
-	} elsif (uc($owl::opcode) eq "USER_LOGOUT") {
+	} elsif ($m->is_logout) {
 	    $out="\@bold(LOGOUT)";
 	} else {
 	    $out="\@bold(UNKNOWN)";
 	}
-	$out.=" for \@bold($owl::sender) at $fields[0] on $fields[2]\n";
+	$out.=" for \@bold($sender) on ".$m->type;
+	if ($m->is_zephyr) {
+	    $out.=" at ".($m->login_host)." on ".($m->login_tty)."\n";
+	}
 	return($out);
-    } elsif (uc($owl::class) eq "MAIL" and uc($owl::instance) eq "INBOX") {
+    }
+
+    if (!$m->is_zephyr && !$m->is_aim) { 
+	return "Unknown message type: ".$m->type."\n";
+    }
+
+    if ($m->is_outgoing) {
+	my $target = $m->recipient;
+	if ($m->is_zephyr) {
+	    $target = $m->zwriteline;
+	    $target =~ s/^zwrite //;
+	}
+	$out = sprintf "\@bold([outgoing %s to %s]) / %s\n", $m->type, $target, $m->time;
+	$out.=indent4($m->body);
+	return $out;
+    }
+
+    if ($m->is_zephyr && $m->is_ping) {
+	return("\@bold(PING) from \@bold($sender)\n");
+    } elsif ($m->is_zephyr && $m->is_mail) {
 	$out = "\@bold(MAIL) ";
-	if ($owl::msg =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; }
-	if ($owl::msg =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; }
-	if ($owl::msg =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; }
+	if ($m->body =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; }
+	if ($m->body =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; }
+	if ($m->body =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; }
+	return($out);
+    }
+
+    if ($m->is_zephyr) {
+	$out = sprintf "[mit,%s,%s] / %s / %s", lc($m->class), 
+	lc($m->instance), $m->time, lc($m->host);
+	if ($m->opcode ne "") {$out.=" op:".$m->opcode;}
+	$out.="\n";
+	$out.= "  \@bold($sender)> ";
+	if ($m->zsig ne "") {
+	    my $zsig = $m->zsig;
+	    $zsig =~ s/(\n.*)+$/ [...]/;
+	    if (length($zsig)+5+length($sender) > 70) {
+		$out.="# ...";
+	    } else {
+		$out.="# $zsig";
+	    }
+	}
+	$out.="\n";		
+    } else {
+	$out = sprintf "[%s] / %s\n", lc($m->type), $m->time;
+	$out.= "  \@bold($sender)> ";
+	$out.="\n";		
+    }
+
+    $out.=indent4($m->body);
+
+    # make personal messages bold
+    if ($m->is_personal) {
+	$out="\@bold{".$out."}";
+    }
+
+    return($out."\n");
+}
+
+sub format_msg_debug {
+    my ($m) = @_;
+    return "\@bold(-------------MESSAGE-------------)\n".($m->serialize).".\n";
+}
+
+sub format_msg_brief {
+    my ($m) = @_;
+    my $out = format_msg_vt($m);
+    $out =~ s/\n/ /g;
+    $out =~ s/                        / /g;
+    return($out."\n");
+}
+
+
+sub format_msg_vt {
+    my ($m) = @_;
+    my ($out, $tmp);
+
+    if ($m->is_admin) {
+	$out = sprintf "%-29s \@i(%s)", "\@bold(OWL ADMIN)", $m->header;
+	$tmp=$m->body;
+	$tmp=~s/^/                       /g;
+	$tmp=~s/\n/\n                       /g;
+	$out.="\n".$tmp;
+	return $out;
+    }
+
+    my $sender=$m->pretty_sender;
+
+    if ($m->is_outgoing) {
+	my $target = $m->recipient;
+	if ($m->is_zephyr) {
+	    $target = $m->zwriteline;
+	    $target =~ s/^zwrite //;
+	}
+	$out = sprintf "%-15s %-13s", "\@bold(OUTGOING)", "to $target via ".$m->type.": ";
+	my $pagewidth = owl::getnumcols()-6;
+	$out .= fill_text($m->body, $pagewidth, 22, 1);
+	return $out;
+    }
+
+    if (!$m->is_zephyr && !$m->is_aim) { 
+	return "Unknown message type: ".$m->type."\n";
+    }
+
+    if ($m->is_zephyr && $m->is_ping) {
+	return (sprintf "%-15s %-13s\n", "\@bold(PING)", $sender);
+    } elsif ($m->is_loginout) {
+	my $state;
+	if ($m->is_login) {
+	    $state="\@bold(LOGIN)";
+	} elsif ($m->is_logout) {
+	    $state="\@bold(LOGOUT)";
+	} else {
+	    $state="\@bold(UNKNOWN)";
+	}
+	my $out = sprintf "%-15s %-13s ", $state, $sender;
+	if ($m->is_zephyr) {
+	    $out .= sprintf "via %s on %s at %s", $m->type, $m->login_host, $m->login_tty;
+	} else {
+	    $out .= sprintf "via %s", $m->type;
+	}
+	return "$out\n";
+		
+    } elsif ($m->is_zephyr && $m->is_mail) {
+	my $body = $m->body;
+	$out = sprintf "%-15s %-13s ", "\@bold(MAIL)", "";
+	if ($body =~ /^From:\s+(.+)\s*$/m) { $out .= "From $1 "; }
+	if ($body =~ /^To:\s+(.+)\s*$/m) { $out .= "To $1 "; }
+	if ($body =~ /^Subject:\s+(.+)\s*$/m) { $out .= "Subject $1 "; }
 	return($out."\n");
     }
 
-    $out = sprintf "[mit,%s,%s] / %s / %s", lc($owl::class), 
-                   lc($owl::instance), $owl::time, lc($owl::host);
-    if ($owl::opcode ne "") {$out.=" op:$owl::opcode";}
-    $out.="\n";
-    $out.= "  \@bold($owl::sender)> ";
-    if ($owl::zsig ne "") {
-	my $zsig = $owl::zsig;
-	$zsig =~ s/(\n.*)+$/ [...]/;
-	if (length($zsig)+5+length($owl::sender) > 70) {
-	    $out.="# ...";
-	} else {
-	    $out.="# $zsig";
-	}
-    }
-    $out.="\n";		
-
-    # indent it
-    $tmp=$owl::msg;
-    $tmp=~s/^/    /g;
-    $tmp=~s/\n/\n    /g;
-    $out.=$tmp;
+    my $channel = "";
+    my $body = $m->body;
+    
+    if ($m->is_zephyr) {
+	my $inst = $m->instance;
+	$channel = $m->class;
+	if (lc($m->class) ne "message" and lc($m->instance) eq "personal") {
+	    $inst = "";
+	}
+	$channel .= "[".$inst."]";
+	$channel = substr($channel,0,13);
+    } else {
+	$channel = "[".$m->type."]";
+    }
+
+    $header = sprintf "%-8s %-13s ", lc($sender), lc($channel);
+
+    if ($body =~ /=/) {
+	# indent it
+	$out.=$header."\n".indent4($body);
+    } else {
+	# fill it
+	my $pagewidth = owl::getnumcols()-6;
+	$out .= $header;
+	$out .= fill_text($body, $pagewidth, 22, 1);
+    }
+
+    # note: no zsig added in this version
 
     # make personal messages bold
-    if (uc($owl::class) eq "MESSAGE" &&
-	uc($owl::instance) eq "PERSONAL") {
+    if ($m->is_personal) {
 	$out="\@bold{".$out."}";
     }
-
-    return($out."\n");
-}
-
-# run when a message is received, and after
-# it has been added to the message list.
-sub owl::receive_msg() {
-    my $out, $tmp;
-
-    $owl::sender=~s/\@ATHENA\.MIT\.EDU$//;
-    $owl::sender=~s/\@local-realm$//;
-
-    if (uc($owl::opcode) eq "PING") {
-	sepbartokens_add(".$owl::sender");
-        owl::command("delete -id $owl::id");
-    } elsif (uc($owl::class) eq "LOGIN") {
-        owl::command("delete -id $owl::id");
-	if (uc($owl::opcode) eq "USER_LOGIN") {
-	    sepbartokens_add(">$owl::sender");
-	    sepbartokens_trim("<$owl::sender");
-	} elsif (uc($owl::opcode) eq "USER_LOGOUT") {
-	    sepbartokens_add("<$owl::sender");
-	    sepbartokens_trim(">$owl::sender");
-	} 
-    } elsif (uc($owl::class) eq "MAIL") {
-        owl::command("delete -id $owl::id");
-	sepbartokens_add("M");
-    }
-
-
-    # make personal messages bold
-    if (uc($owl::class) eq "MESSAGE" &&
-	uc($owl::instance) eq "PERSONAL") {
-	sepbartokens_trim(".$owl::sender");
-	sepbartokens_add(":$owl::sender");
-    }
-
-    return 1;
-}
+    return($out);
+}
+
+sub fill_text {
+    my ($in, $width, $indent, $unindent_first) = @_;
+    $indent = 0 if (@_ < 3);
+    my $unindent = $indent if ($unindent_first);
+    my @words = split " ", $in;
+    my $out = "";
+    my $outline = "";
+    if (!$unindent_first) {
+	my $outline = " "x$indent;
+    }
+    for my $w (@words) {
+	if (($outline ne "") 
+	    && (length($outline)+length($w) > $width-$unindent)) {
+	    $out .= $outline."\n";
+	    $outline = " "x$indent;
+	    $unindent = 0;
+	}
+	if ($outline =~ /.*\.$/) {
+	    $outline .= "  ";
+	} elsif ($outline ne "") {
+	    $outline .= " ";
+	}
+	$outline .= $w;
+    }
+    $out .= $outline . "\n";    
+}
Index: functions.c
===================================================================
--- functions.c	(revision a352335c16b1820d3683357330a3b984458ac2d0)
+++ functions.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -78,4 +78,32 @@
 }
 
+void owl_function_show_styles() {
+  owl_list l;
+  owl_fmtext fm;
+
+  owl_fmtext_init_null(&fm);
+  owl_fmtext_append_bold(&fm, "Styles:\n");
+  owl_global_get_style_names(&g, &l);
+  owl_fmtext_append_list(&fm, &l, "\n", owl_function_style_describe);
+  owl_fmtext_append_normal(&fm, "\n");
+  owl_function_popless_fmtext(&fm);
+  owl_list_free_all(&l, owl_free);
+  owl_fmtext_free(&fm);
+}
+
+char *owl_function_style_describe(void *name) {
+  char *desc, *s;
+  owl_style *style;
+  style = owl_global_get_style_by_name(&g, name);
+  if (style) {
+    desc = owl_style_get_description(style);
+  } else {
+    desc = "???";
+  }
+  s = owl_sprintf("%-20s - %s%s", name, 
+		  0==owl_style_validate(style)?"":"[INVALID] ",
+		  desc);
+  return s;
+}
 
 char *owl_function_cmd_describe(void *name)
@@ -741,5 +769,5 @@
 
   /* execute the commands in shutdown */
-  ret = owl_config_execute("owl::shutdown();");
+  ret = owl_perlconfig_execute("owl::shutdown();");
   if (ret) owl_free(ret);
 
@@ -2051,5 +2079,5 @@
   buff = skiptokens(buff, 1);
 
-  perlout = owl_config_execute(buff);
+  perlout = owl_perlconfig_execute(buff);
   if (perlout) { 
     if (type==1) {
Index: global.c
===================================================================
--- global.c	(revision a352335c16b1820d3683357330a3b984458ac2d0)
+++ global.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -53,5 +53,5 @@
   owl_list_create(&(g->puntlist));
   owl_list_create(&(g->messagequeue));
-  owl_list_create(&(g->stylelist));
+  owl_dict_create(&(g->styledict));
   g->curmsg_vert_offset=0;
   g->resizepending=0;
@@ -390,4 +390,7 @@
   _owl_global_setup_windows(g);
 
+  /* in case any styles rely on the current width */
+  owl_messagelist_invalidate_formats(owl_global_get_msglist(g));
+
   /* refresh stuff */
   g->needrefresh=1;
@@ -774,20 +777,17 @@
 owl_style *owl_global_get_style_by_name(owl_global *g, char *name)
 {
-  int i, j;
-  owl_style *s;
-  
-  j=owl_list_get_size(&(g->stylelist));
-  for (i=0; i<j; i++) {
-    s=owl_list_get_element(&(g->stylelist), i);
-    if (owl_style_matches_name(s, name)) {
-      return(s);
-    }
-  }
-  return(NULL);
+  return owl_dict_find_element(&(g->styledict), name);
+}
+
+/* creates a list and fills it in with keys.  duplicates the keys, 
+ * so they will need to be freed by the caller. */
+int owl_global_get_style_names(owl_global *g, owl_list *l) {
+  return owl_dict_get_keys(&(g->styledict), l);
 }
 
 void owl_global_add_style(owl_global *g, owl_style *s)
 {
-  owl_list_append_element(&(g->stylelist), s);
+  owl_dict_insert_element(&(g->styledict), owl_style_get_name(s), 
+			  s, (void(*)(void*))owl_style_free);
 }
 
Index: message.c
===================================================================
--- message.c	(revision 9ceee9d93177e80e7794f45d5ba9e611169e4d55)
+++ message.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -574,4 +574,54 @@
 }
 
+char *owl_message_get_type(owl_message *m) {
+  switch (m->type) {
+  case OWL_MESSAGE_TYPE_ADMIN:
+    return("admin");
+  case OWL_MESSAGE_TYPE_ZEPHYR:
+    return("zephyr");
+  case OWL_MESSAGE_TYPE_GENERIC:
+    return("generic");
+  case OWL_MESSAGE_TYPE_AIM:
+    return("aim");
+  case OWL_MESSAGE_TYPE_JABBER:
+    return("jabber");
+  case OWL_MESSAGE_TYPE_ICQ:
+    return("icq");
+  case OWL_MESSAGE_TYPE_YAHOO:
+    return("yahoo");
+  case OWL_MESSAGE_TYPE_MSN:
+    return("msn");
+  default:
+    return("unknown");
+  }
+}
+
+char *owl_message_get_direction(owl_message *m) {
+  switch (m->direction) {
+  case OWL_MESSAGE_DIRECTION_IN:
+    return("in");
+  case OWL_MESSAGE_DIRECTION_OUT:
+    return("out");
+  case OWL_MESSAGE_DIRECTION_NONE:
+    return("none");
+  default:
+    return("unknown");
+  }
+}
+
+char *owl_message_get_login(owl_message *m) {
+  if (owl_message_is_login(m)) {
+    return "login";
+  } else if (owl_message_is_logout(m)) {
+    return "logout";
+  } else {
+    return "none";
+  }
+}
+
+char *owl_message_get_header(owl_message *m) {
+  return owl_message_get_attribute_value(m, "adminheader");
+}
+
 /* return 1 if the message contains "string", 0 otherwise.  This is
  * case insensitive because the functions it uses are
@@ -798,2 +848,4 @@
   owl_fmtext_free(&(m->fmtext));
 }
+
+
Index: owl.c
===================================================================
--- owl.c	(revision a352335c16b1820d3683357330a3b984458ac2d0)
+++ owl.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -33,5 +33,5 @@
   int newmsgs, zpendcount, nexttimediff;
   struct sigaction sigact;
-  char *configfile, *tty, *perlout, **argvsave, buff[LINE], startupmsg[LINE];
+  char *configfile, *tty, *perlout, *perlerr, **argvsave, buff[LINE], startupmsg[LINE];
   owl_filter *f;
   owl_style *s;
@@ -152,13 +152,16 @@
   /* setup the built-in styles */
   s=owl_malloc(sizeof(owl_style));
-  owl_style_create_internal(s, "default", &owl_stylefunc_default);
+  owl_style_create_internal(s, "default", &owl_stylefunc_default,
+			    "Default message formatting");
   owl_global_add_style(&g, s);
 
   s=owl_malloc(sizeof(owl_style));
-  owl_style_create_internal(s, "basic", &owl_stylefunc_basic);
+  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);
+  owl_style_create_internal(s, "oneline", &owl_stylefunc_oneline,
+			    "Formats for one-line-per-message");
   owl_global_add_style(&g, s);
 
@@ -224,8 +227,8 @@
   /* read the config file */
   owl_context_set_readconfig(owl_global_get_context(&g));
-  ret=owl_readconfig(configfile);
-  if (ret) {
+  perlerr=owl_perlconfig_readconfig(configfile);
+  if (perlerr) {
     endwin();
-    printf("\nError parsing configfile\n");
+    fprintf(stderr, "\nError parsing configfile: %s\n", perlerr);
     exit(1);
   }
@@ -235,11 +238,23 @@
     owl_function_debugmsg("Found perl formatting");
     s=owl_malloc(sizeof(owl_style));
-    owl_style_create_perl(s, "perl", "owl::format_msg");
+    owl_style_create_perl(s, "perl", "owl::_format_msg_legacy_wrap",
+			  "User-defined perl style that calls owl::format_msg"
+			  "with legacy global variable support");
     owl_global_add_style(&g, s);
     owl_global_set_default_style(&g, "perl");
   }
 
+  /* set the startup and default style, based on userclue and presence of a
+   * formatting function */
+  if (owl_global_is_config_format(&g)) {
+    owl_global_set_default_style(&g, "perl");
+  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
+    owl_global_set_default_style(&g, "default");
+  } else {
+    owl_global_set_default_style(&g, "basic");
+  }
+
   /* execute the startup function in the configfile */
-  perlout = owl_config_execute("owl::startup();");
+  perlout = owl_perlconfig_execute("owl::startup();");
   if (perlout) owl_free(perlout);
   owl_function_debugmsg("-- Owl Startup --");
@@ -273,20 +288,10 @@
   }
 
-  /* set the startup and default style, based on userclue and presence of a
-   * formatting function */
-  if (owl_global_is_config_format(&g)) {
-    owl_view_set_style(owl_global_get_current_view(&g), owl_global_get_style_by_name(&g, "perl"));
-    owl_global_set_default_style(&g, "perl");
-  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
-    owl_view_set_style(owl_global_get_current_view(&g), owl_global_get_style_by_name(&g, "default"));
-    owl_global_set_default_style(&g, "default");
-  } else {
-    owl_view_set_style(owl_global_get_current_view(&g), owl_global_get_style_by_name(&g, "basic"));
-    owl_global_set_default_style(&g, "basic");
-  }
+  owl_view_set_style(owl_global_get_current_view(&g), 
+		     owl_global_get_style_by_name(&g, owl_global_get_default_style(&g)));   
 
   /* welcome message */
   strcpy(startupmsg, "-------------------------------------------------------------------------\n");
-  sprintf(buff,      "Welcome to Owl version %s.  Press 'h' for on line help. \n", OWL_VERSION_STRING);
+  sprintf(buff,      "Welcome to Owl version %s.  Press 'h' for on-line help. \n", OWL_VERSION_STRING);
   strcat(startupmsg, buff);
   strcat(startupmsg, "                                                                         \n");
@@ -395,5 +400,5 @@
 
       /* let the config know the new message has been received */
-      owl_config_getmsg(m, "owl::receive_msg();");
+      owl_perlconfig_getmsg(m, 0, NULL);
 
       /* add it to any necessary views; right now there's only the current view */
Index: owl.h
===================================================================
--- owl.h	(revision 687345590215e63bdcb0d5f5db2ae601600f0468)
+++ owl.h	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -21,6 +21,6 @@
 static const char owl_h_fileIdent[] = "$Id$";
 
-#define OWL_VERSION         2.0.8-pre-1
-#define OWL_VERSION_STRING "2.0.8-pre-1"
+#define OWL_VERSION         2.0.8-pre-2
+#define OWL_VERSION_STRING "2.0.8-pre-2"
 
 #define OWL_DEBUG 0
@@ -274,4 +274,5 @@
 typedef struct _owl_style {
   char *name;
+  char *description;
   int type;
   char *perlfuncname;
@@ -451,5 +452,5 @@
   owl_buddylist buddylist;  /* list of logged in AIM buddies */
   owl_list messagequeue;    /* for queueing up aim and other messages */
-  owl_list stylelist;       /* global list of available styles */
+  owl_dict styledict;       /* global dictionary of available styles */
   char *response;           /* response to the last question asked */
   int havezephyr;
Index: perlconfig.c
===================================================================
--- perlconfig.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
+++ perlconfig.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -0,0 +1,301 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "owl.h"
+#include <perl.h>
+#include "XSUB.h"
+
+static const char fileIdent[] = "$Id$";
+
+extern char *owl_perlwrap_codebuff;
+
+extern XS(boot_owl);
+
+static void owl_perl_xs_init(pTHX) {
+  char *file = __FILE__;
+  dXSUB_SYS;
+  {
+    newXS("owl::bootstrap", boot_owl, file);
+  }
+}
+
+SV *owl_perlconfig_message2hashref(owl_message *m) { /*noproto*/
+  HV *h;
+  SV *hr;
+  char *ptr, *ptr2, *blessas;
+  int len, i, j;
+
+  if (!m) return &PL_sv_undef;
+  h = newHV();
+
+#define MSG2H(h,field) hv_store(h, #field, strlen(#field), \
+			      newSVpv(owl_message_get_##field(m),0), 0)
+
+  if (owl_message_is_type_zephyr(m)
+      && owl_message_is_direction_in(m)) {
+    /* Handle zephyr-specific fields... */
+    AV *av_zfields;
+
+    av_zfields = newAV();
+    j=owl_zephyr_get_num_fields(owl_message_get_notice(m));
+    for (i=0; i<j; i++) {
+      ptr=owl_zephyr_get_field(owl_message_get_notice(m), i+1, &len);
+      ptr2=owl_malloc(len+1);
+      memcpy(ptr2, ptr, len);
+      ptr2[len]='\0';
+      av_push(av_zfields, newSVpvn(ptr2, len));
+      owl_free(ptr2);
+    }
+    hv_store(h, "fields", strlen("fields"), newRV_noinc((SV*)av_zfields), 0);
+
+    hv_store(h, "auth", strlen("auth"), 
+	     newSVpv(owl_zephyr_get_authstr(owl_message_get_notice(m)),0),0);
+  }
+
+  MSG2H(h, type);
+  MSG2H(h, direction);
+  MSG2H(h, class);
+  MSG2H(h, instance);
+  MSG2H(h, sender);
+  MSG2H(h, realm);
+  MSG2H(h, recipient);
+  MSG2H(h, opcode);
+  MSG2H(h, hostname);
+  MSG2H(h, body);
+  MSG2H(h, login);
+  MSG2H(h, zsig);
+  MSG2H(h, zwriteline);
+  if (owl_message_get_header(m)) {
+    MSG2H(h, header); 
+  }
+  hv_store(h, "time", strlen("time"), newSVpv(owl_message_get_timestr(m),0),0);
+  hv_store(h, "id", strlen("id"), newSViv(owl_message_get_id(m)),0);
+  hv_store(h, "deleted", strlen("deleted"), newSViv(owl_message_is_delete(m)),0);
+
+  if (owl_message_is_type_zephyr(m))       blessas = "owl::Message::Zephyr";
+  else if (owl_message_is_type_aim(m))     blessas = "owl::Message::AIM";
+  else if (owl_message_is_type_admin(m))   blessas = "owl::Message::Admin";
+  else if (owl_message_is_type_generic(m)) blessas = "owl::Message::Generic";
+  else                                     blessas = "owl::Message";
+
+  hr = sv_2mortal(newRV_noinc((SV*)h));
+  return sv_bless(hr, gv_stashpv(blessas,0));
+}
+
+
+SV *owl_perlconfig_curmessage2hashref(void) { /*noproto*/
+  int curmsg;
+  owl_view *v;
+  v=owl_global_get_current_view(&g);
+  if (owl_view_get_size(v) < 1) {
+    return &PL_sv_undef;
+  }
+  curmsg=owl_global_get_curmsg(&g);
+  return owl_perlconfig_message2hashref(owl_view_get_element(v, curmsg));
+}
+
+
+/* Calls in a scalar context, passing it a hash reference.
+   If return value is non-null, caller must free. */
+char *owl_perlconfig_call_with_message(char *subname, owl_message *m) {
+  dSP ;
+  int count, len;
+  SV *msgref, *srv;
+  char *out, *preout;
+  
+  ENTER ;
+  SAVETMPS;
+  
+  PUSHMARK(SP) ;
+  msgref = owl_perlconfig_message2hashref(m);
+  XPUSHs(msgref);
+  PUTBACK ;
+  
+  count = call_pv(subname, G_SCALAR|G_EVAL|G_KEEPERR);
+  
+  SPAGAIN ;
+
+  if (SvTRUE(ERRSV)) {
+    STRLEN n_a;
+    owl_function_makemsg("Perl Error: '%s'", SvPV(ERRSV, n_a));
+  }
+
+  if (count != 1) {
+    fprintf(stderr, "bad perl!  no biscuit!  returned wrong count!\n");
+    abort();
+  }
+
+  srv = POPs;
+
+  if (srv) {
+    preout=SvPV(srv, len);
+    out = owl_malloc(strlen(preout)+1);
+    strncpy(out, preout, len);
+    out[len] = '\0';
+  } else {
+    out = NULL;
+  }
+  
+  PUTBACK ;
+  FREETMPS ;
+  LEAVE ;
+
+  return out;
+}
+
+char *owl_perlconfig_readconfig(char *file) {
+  int ret;
+  PerlInterpreter *p;
+  char filename[1024];
+  char *embedding[5];
+  struct stat statbuff;
+
+  if (file==NULL) {
+    sprintf(filename, "%s/%s", getenv("HOME"), ".owlconf");
+  } else {
+    strcpy(filename, file);
+  }
+  embedding[0]="";
+  embedding[1]=filename;
+  embedding[2]=0;
+
+  /* create and initialize interpreter */
+  p=perl_alloc();
+  owl_global_set_perlinterp(&g, (void*)p);
+  perl_construct(p);
+
+  owl_global_set_no_have_config(&g);
+
+  ret=stat(filename, &statbuff);
+  if (ret) {
+    return NULL;
+  }
+
+  ret=perl_parse(p, owl_perl_xs_init, 2, embedding, NULL);
+  if (ret || SvTRUE(ERRSV)) {
+    STRLEN n_a;
+    return owl_strdup(SvPV(ERRSV, n_a));
+  }
+
+  ret=perl_run(p);
+  if (ret || SvTRUE(ERRSV)) {
+    STRLEN n_a;
+    return owl_strdup(SvPV(ERRSV, n_a));
+  }
+
+  owl_global_set_have_config(&g);
+
+  /* create legacy variables */
+  perl_get_sv("owl::id", TRUE);
+  perl_get_sv("owl::class", TRUE);
+  perl_get_sv("owl::instance", TRUE);
+  perl_get_sv("owl::recipient", TRUE);
+  perl_get_sv("owl::sender", TRUE);
+  perl_get_sv("owl::realm", TRUE);
+  perl_get_sv("owl::opcode", TRUE);
+  perl_get_sv("owl::zsig", TRUE);
+  perl_get_sv("owl::msg", TRUE);
+  perl_get_sv("owl::time", TRUE);
+  perl_get_sv("owl::host", TRUE);
+  perl_get_av("owl::fields", TRUE);
+  
+  perl_eval_pv(owl_perlwrap_codebuff, FALSE);
+
+  if (SvTRUE(ERRSV)) {
+    STRLEN n_a;
+    return owl_strdup(SvPV(ERRSV, n_a));
+  }
+
+  /* check if we have the formatting function */
+  if (owl_perlconfig_is_function("owl::format_msg")) {
+    owl_global_set_config_format(&g, 1);
+  }
+
+  return(NULL);
+}
+
+/* returns whether or not a function exists */
+int owl_perlconfig_is_function(char *fn) {
+  if (perl_get_cv(fn, FALSE)) return(1);
+  else return(0);
+}
+
+/* returns 0 on success */
+int owl_perlconfig_get_hashkeys(char *hashname, owl_list *l) {
+  HV *hv;
+  HE *he;
+  char *key;
+  I32 i;
+
+  if (owl_list_create(l)) return(-1);
+  hv = get_hv(hashname, FALSE);
+  if (!hv) return(-1);
+  i = hv_iterinit(hv);
+  while ((he = hv_iternext(hv))) {
+    key = hv_iterkey(he, &i);
+    if (key) {
+      owl_list_append_element(l, owl_strdup(key));
+    }
+  }
+  return(0);
+}
+
+/* caller is responsible for freeing returned string */
+char *owl_perlconfig_execute(char *line) {
+  STRLEN len;
+  SV *response;
+  char *out, *preout;
+
+  if (!owl_global_have_config(&g)) return NULL;
+
+  /* execute the subroutine */
+  response = perl_eval_pv(line, FALSE);
+
+  if (SvTRUE(ERRSV)) {
+    STRLEN n_a;
+    owl_function_makemsg("Perl Error: '%s'", SvPV(ERRSV, n_a));
+  }
+
+  preout=SvPV(response, len);
+  /* leave enough space in case we have to add a newline */
+  out = owl_malloc(strlen(preout)+2);
+  strncpy(out, preout, len);
+  out[len] = '\0';
+  if (!strlen(out) || out[strlen(out)-1]!='\n') {
+    strcat(out, "\n");
+  }
+
+  return(out);
+}
+
+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
+					   :"owl::_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("owl::receive_msg")) {
+      owl_perlconfig_call_with_message(subname?subname
+				       :"owl::_receive_msg_legacy_wrap", m);
+    }
+    if (ptr) owl_free(ptr);
+    return(NULL);
+  }
+}
Index: perlglue.xs
===================================================================
--- perlglue.xs	(revision 1fd0b25bc362ef6deee5d05e4558ce154f8c6f5c)
+++ perlglue.xs	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -1,13 +1,17 @@
 static const char fileIdent[] = "$Id$";
 
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
+#include <zephyr/zephyr.h>
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
 
 /* Yeah, we should just include owl.h, but curses and perl don't play nice. */
-extern char *owl_function_command(char *);
-extern void owl_free(void *);
+extern char *owl_function_command(char *cmd);
+extern void owl_free(void *x);
+extern SV *owl_perlconfig_curmessage2hashref();
 extern int owl_zwrite_create_and_send_from_line(char *, char *);
 extern char *owl_function_ztext_stylestrip(char *);
+extern void g;
+extern int owl_global_get_cols(void*);
 
 MODULE = owl		PACKAGE = owl		
@@ -26,6 +30,32 @@
 		if (rv) owl_free(rv);
 
+SV *
+getcurmsg()
+	CODE:
+		ST(0) = owl_perlconfig_curmessage2hashref();
+
+int
+getnumcols()
+	CODE:
+		RETVAL = owl_global_get_cols(&g);
+	OUTPUT:
+		RETVAL
+
+char *
+zephyr_getrealm()
+	CODE:
+		RETVAL = ZGetRealm();
+	OUTPUT:
+		RETVAL
+
+char *
+zephyr_getsender()
+	CODE:
+		RETVAL = ZGetSender();
+	OUTPUT:
+		RETVAL
+
 void
-send_zwrite(cmd,msg)
+zephyr_zwrite(cmd,msg)
 	char *cmd
 	char *msg
Index: perlwrap.pm
===================================================================
--- perlwrap.pm	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
+++ perlwrap.pm	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -0,0 +1,230 @@
+# $Id$
+#
+# This is all linked into the binary and evaluated when perl starts up...
+#
+#####################################################################
+#####################################################################
+
+package owl;
+
+# bootstrap in C bindings and glue
+bootstrap owl 1.2;
+
+# populate global variable space for legacy owlconf files 
+sub _format_msg_legacy_wrap {
+    my ($m) = @_;
+    $m->legacy_populate_global();
+    return &owl::format_msg($m);
+}
+
+# populate global variable space for legacy owlconf files 
+sub _receive_msg_legacy_wrap {
+    my ($m) = @_;
+    $m->legacy_populate_global();
+    return &owl::receive_msg($m);
+}
+
+# make owl::<command>("foo") be aliases to owl::command("<command> foo");
+sub AUTOLOAD {
+    my $called = $AUTOLOAD;
+    $called =~ s/.*:://;
+    return &owl::command("$called ".join(" ",@_));
+}
+
+#####################################################################
+#####################################################################
+
+package owl::Message;
+
+sub type        { return shift->{"type"}; }
+sub direction   { return shift->{"direction"}; }
+sub time        { return shift->{"time"}; }
+sub id          { return shift->{"id"}; }
+sub body        { return shift->{"body"}; }
+sub sender      { return shift->{"sender"}; }
+sub recipient   { return shift->{"recipient"}; }
+sub login       { return shift->{"login"}; }
+
+sub is_login    { return shift->login eq "login"; }
+sub is_logout   { return shift->login eq "logout"; }
+sub is_loginout { my $m=shift; return ($m->is_login or $m->is_logout); }
+sub is_incoming { return (shift->{"direction"} eq "in"); }
+sub is_outgoing { return (shift->{"direction"} eq "out"); }
+
+sub is_deleted  { return shift->{"deleted"}; }
+
+sub is_zephyr   { return (shift->{"type"} eq "zephyr"); }
+sub is_aim      { return (shift->{"type"} eq "aim"); }
+sub is_admin    { return (shift->{"type"} eq "admin"); }
+sub is_generic  { return (shift->{"type"} eq "generic"); }
+
+# These are overridden by appropriate message types
+sub is_ping     { return 0; }
+sub is_mail     { return 0; }
+sub class       { return undef; }
+sub instance    { return undef; }
+sub realm       { return undef; }
+sub opcode      { return undef; }
+sub header      { return undef; }
+sub host        { return undef; }
+sub hostname    { return undef; }
+sub auth        { return undef; }
+sub fields      { return undef; }
+sub zsig        { return undef; }
+sub zwriteline  { return undef; }
+
+sub pretty_sender { return shift->sender; }
+
+sub delete {
+    my ($m) = @_;
+    &owl::command("delete --id ".$m->id);
+}
+
+sub undelete {
+    my ($m) = @_;
+    &owl::command("undelete --id ".$m->id);
+}
+
+# Serializes the message into something similar to the zwgc->vt format
+sub serialize {
+    my ($this) = @_;
+    my $s;
+    for my $f (keys %$this) {
+	my $val = $this->{$f};
+	if (ref($val) eq "ARRAY") {
+	    for my $i (0..@$val-1) {
+		my $aval;
+		$aval = $val->[$i];
+		$aval =~ s/\n/\n$f.$i: /g;
+		$s .= "$f.$i: $aval\n";	   
+	    }
+	} else {
+	    $val =~ s/\n/\n$f: /g;
+	    $s .= "$f: $val\n";
+	}
+    }
+    return $s;
+}
+
+# Populate the annoying legacy global variables
+sub legacy_populate_global {
+    my ($m) = @_;
+    $owl::direction  = $m->direction ;
+    $owl::type       = $m->type      ;
+    $owl::id         = $m->id        ;
+    $owl::class      = $m->class     ;
+    $owl::instance   = $m->instance  ;
+    $owl::recipient  = $m->recipient ;
+    $owl::sender     = $m->sender    ;
+    $owl::realm      = $m->realm     ;
+    $owl::opcode     = $m->opcode    ;
+    $owl::zsig       = $m->zsig      ;
+    $owl::msg        = $m->body      ;
+    $owl::time       = $m->time      ;
+    $owl::host       = $m->host      ;
+    if ($m->fields) {
+	@owl::fields = @{$m->fields};
+	@main::fields = @{$m->fields};
+    } else {
+	@owl::fields = undef;
+	@main::fields = undef;
+    }
+}
+
+#####################################################################
+#####################################################################
+
+package owl::Message::Admin;
+
+@ISA = qw( owl::Message );
+
+sub header       { return shift->{"header"}; }
+
+#####################################################################
+#####################################################################
+
+package owl::Message::Generic;
+
+@ISA = qw( owl::Message );
+
+#####################################################################
+#####################################################################
+
+package owl::Message::AIM;
+
+@ISA = qw( owl::Message );
+
+# all non-loginout AIM messages are personal for now...
+sub is_personal { 
+    return !(shift->is_loginout);
+}
+
+#####################################################################
+#####################################################################
+
+package owl::Message::Zephyr;
+
+@ISA = qw( owl::Message );
+
+sub login_tty { 
+    my ($m) = @_;
+    return undef if (!$m->is_loginout);
+    return $m->fields->[2];
+}
+
+sub login_host { 
+    my ($m) = @_;
+    return undef if (!$m->is_loginout);
+    return $m->fields->[0];
+}
+
+sub zwriteline  { return shift->{"zwriteline"}; }
+
+sub zsig        { return shift->{"zsig"}; }
+
+sub is_ping     { return (lc(shift->opcode) eq "ping"); }
+
+sub is_private {
+    my ($m) = @_;
+    return (lc($m->recipient) eq lc(owl::zephyr_getsender()));
+}
+
+sub is_personal { 
+    my ($m) = @_;
+    return ((lc($m->class) eq "message")
+	    && (lc($m->instance) eq "personal")
+	    && $m->is_private);
+}
+
+sub is_mail { 
+    my ($m) = @_;
+    return ((lc($m->class) eq "mail") && $m->is_private);
+}
+
+sub pretty_sender {
+    my ($m) = @_;
+    my $sender = $m->sender;
+    my $realm = owl::zephyr_getrealm();
+    $sender =~ s/\@$realm$//;
+    return $sender;
+}
+
+# These are arguably zephyr-specific
+sub class       { return shift->{"class"}; }
+sub instance    { return shift->{"instance"}; }
+sub realm       { return shift->{"realm"}; }
+sub opcode      { return shift->{"opcode"}; }
+sub host        { return shift->{"hostname"}; }
+sub hostname    { return shift->{"hostname"}; }
+sub header      { return shift->{"header"}; }
+sub auth        { return shift->{"auth"}; }
+sub fields      { return shift->{"fields"}; }
+sub zsig        { return shift->{"zsig"}; }
+
+#####################################################################
+#####################################################################
+
+# switch to package main when we're done
+package main;
+
+1;
Index: adconfig.c
===================================================================
--- readconfig.c	(revision 290f290424b7db498f7acbe31273ee01df0aeb74)
+++ 	(revision )
@@ -1,254 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include "owl.h"
-#include <perl.h>
-#include "XSUB.h"
-
-static const char fileIdent[] = "$Id$";
-
-extern XS(boot_owl);
-
-static void owl_perl_xs_init(pTHX) {
-  char *file = __FILE__;
-  dXSUB_SYS;
-  {
-    newXS("owl::bootstrap", boot_owl, file);
-  }
-}
-
-
-int owl_readconfig(char *file) {
-  int ret;
-  PerlInterpreter *p;
-  char *codebuff, filename[1024];
-  char *embedding[5];
-  struct stat statbuff;
-
-  if (file==NULL) {
-    sprintf(filename, "%s/%s", getenv("HOME"), ".owlconf");
-  } else {
-    strcpy(filename, file);
-  }
-  embedding[0]="";
-  embedding[1]=filename;
-  embedding[2]=0;
-
-  /* create and initialize interpreter */
-  p=perl_alloc();
-  owl_global_set_perlinterp(&g, (void*)p);
-  perl_construct(p);
-
-  /* start by assuming no config */
-  owl_global_set_no_have_config(&g);
-
-  ret=stat(filename, &statbuff);
-  if (ret) {
-    return(0);
-  }
-
-  /* This is the CMU code for reading a site owlconf.  Not sure if I
-     want it yet */
-  /*
-  ret=stat(filename, &statbuff);
-  if (ret) {
-    sprintf(filename, "%s/%s", DATADIR, "owl/owlconf");
-    ret=stat(filename, &statbuff);
-    if (ret) {
-      return(0);
-    }
-  }
-  */
-
-  ret=perl_parse(p, owl_perl_xs_init, 2, embedding, NULL);
-  if (ret) return(-1);
-  ret=perl_run(p);
-  if (ret) return(-1);
-
-  /* if we get this far, we have a good config file */
-  owl_global_set_have_config(&g);
-
-  /* create variables */
-  perl_get_sv("owl::id", TRUE);
-  perl_get_sv("owl::type", TRUE);
-  perl_get_sv("owl::direction", TRUE);
-  perl_get_sv("owl::class", TRUE);
-  perl_get_sv("owl::instance", TRUE);
-  perl_get_sv("owl::recipient", TRUE);
-  perl_get_sv("owl::sender", TRUE);
-  perl_get_sv("owl::realm", TRUE);
-  perl_get_sv("owl::opcode", TRUE);
-  perl_get_sv("owl::zsig", TRUE);
-  perl_get_sv("owl::msg", TRUE);
-  perl_get_sv("owl::time", TRUE);
-  perl_get_sv("owl::host", TRUE);
-  perl_get_sv("owl::login", TRUE);
-  perl_get_sv("owl::auth", TRUE);
-  perl_get_av("owl::fields", TRUE);
-  
-  /* perl bootstrapping code */
-  codebuff = 
-    "                                             \n"
-    "package owl;                                 \n"
-    "                                             \n"
-    "bootstrap owl 0.01;                          \n"
-    "                                             \n"
-    "package main;                                \n";
-
-  perl_eval_pv(codebuff, FALSE);
-
-
-  /* check if we have the formatting function */
-  if (perl_get_cv("owl::format_msg", FALSE)) {
-    owl_global_set_config_format(&g, 1);
-  }
-  return(0);
-}
-
-
-/* caller is responsible for freeing returned string */
-char *owl_config_execute(char *line) {
-  STRLEN len;
-  SV *response;
-  char *out, *preout;
-
-  if (!owl_global_have_config(&g)) return NULL;
-
-  /* execute the subroutine */
-  response = perl_eval_pv(line, FALSE);
-
-  preout=SvPV(response, len);
-  /* leave enough space in case we have to add a newline */
-  out = owl_malloc(strlen(preout)+2);
-  strncpy(out, preout, len);
-  out[len] = '\0';
-  if (!strlen(out) || out[strlen(out)-1]!='\n') {
-    strcat(out, "\n");
-  }
-
-  return(out);
-}
-
-char *owl_config_getmsg(owl_message *m, char *funcname) {
-  int i, j, len;
-  char *ptr, *ptr2;
-  char runstr[LINE];
-
-  if (!owl_global_have_config(&g)) return("");
-
-  /* set owl::msg */
-  ptr=owl_message_get_body(m);
-  len=strlen(ptr);
-  ptr2=owl_malloc(len+20);
-  memcpy(ptr2, ptr, len);
-  ptr2[len]='\0';
-  if (ptr2[len-1]!='\n') {
-    strcat(ptr2, "\n");
-  }
-  sv_setpv(perl_get_sv("owl::msg", TRUE), ptr2);
-  owl_free(ptr2);
-
-  /* set owl::zsig */
-  ptr=owl_message_get_zsig(m);
-  len=strlen(ptr);
-  if (len>0) {
-    ptr2=owl_malloc(len+20);
-    memcpy(ptr2, ptr, len);
-    ptr2[len]='\0';
-    if (ptr2[len-1]=='\n') {  /* do we really need this? */
-      ptr2[len-1]='\0';
-    }
-    sv_setpv(perl_get_sv("owl::zsig", TRUE), ptr2);
-    owl_free(ptr2);
-  } else {
-    sv_setpv(perl_get_sv("owl::zsig", TRUE), "");
-  }
-
-  /* set owl::type */
-  sv_setpv(perl_get_sv("owl::type", TRUE), owl_message_type_to_string(m));
-
-
-  /* set owl::auth default */
-  sv_setpv(perl_get_sv("owl::auth", TRUE), "YES");
-
-  /* set owl::direction */
-  if (owl_message_is_direction_in(m)) {
-    sv_setpv(perl_get_sv("owl::direction", TRUE), "in");
-
-    /* Change auth value for in messages */
-    sv_setpv(perl_get_sv("owl::auth", TRUE), owl_zephyr_get_authstr(owl_message_get_notice(m)));
-
-  } else if (owl_message_is_direction_out(m)) {
-    sv_setpv(perl_get_sv("owl::direction", TRUE), "out");
-  } else if (owl_message_is_direction_none(m)) {
-    sv_setpv(perl_get_sv("owl::direction", TRUE), "none");
-  } else {
-    sv_setpv(perl_get_sv("owl::direction", TRUE), "unknown");
-  }
-
-  /* set owl::login */
-  if (owl_message_is_login(m)) {
-    sv_setpv(perl_get_sv("owl::login", TRUE), "login");
-  } else if (owl_message_is_logout(m)) {
-    sv_setpv(perl_get_sv("owl::login", TRUE), "logout");
-  } else {
-    sv_setpv(perl_get_sv("owl::login", TRUE), "none");
-  }
-
-  /* set everything else */
-  sv_setpv(perl_get_sv("owl::class", TRUE), owl_message_get_class(m));
-  sv_setpv(perl_get_sv("owl::instance", TRUE), owl_message_get_instance(m));
-  sv_setpv(perl_get_sv("owl::sender", TRUE), owl_message_get_sender(m));
-  sv_setpv(perl_get_sv("owl::realm", TRUE), owl_message_get_realm(m));
-  sv_setpv(perl_get_sv("owl::recipient", TRUE), owl_message_get_recipient(m));
-  sv_setpv(perl_get_sv("owl::opcode", TRUE), owl_message_get_opcode(m));
-  sv_setpv(perl_get_sv("owl::time", TRUE), owl_message_get_timestr(m));
-  sv_setpv(perl_get_sv("owl::host", TRUE), owl_message_get_hostname(m));
-  sv_setiv(perl_get_sv("owl::id", TRUE), owl_message_get_id(m));
-
-  /* free old @fields ? */
-  /* I don't think I need to do this, but ask marc to make sure */
-  /*
-  j=av_len(perl_get_av("fields", TRUE));
-  for (i=0; i<j; i++) {
-    tmpsv=av_pop(perl_get_av("fields", TRUE));
-    SvREFCNT_dec(tmpsv);
-  }
-  */
-
-  /* set owl::fields */
-  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
-    av_clear(perl_get_av("owl::fields", TRUE));
-    j=owl_zephyr_get_num_fields(owl_message_get_notice(m));
-    for (i=0; i<j; i++) {
-      ptr=owl_zephyr_get_field(owl_message_get_notice(m), i+1, &len);
-      ptr2=owl_malloc(len+10);
-      memcpy(ptr2, ptr, len);
-      ptr2[len]='\0';
-      av_push(perl_get_av("owl::fields", TRUE), newSVpvn(ptr2, len));
-      owl_free(ptr2);
-    }
-  }
-
-  /* for backwards compatibilty, because I'm an idiot */
-  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
-    av_clear(perl_get_av("fields", TRUE));
-    j=owl_zephyr_get_num_fields(owl_message_get_notice(m));
-    for (i=0; i<j; i++) {
-      ptr=owl_zephyr_get_field(owl_message_get_notice(m), i+1, &len);
-      ptr2=owl_malloc(len+10);
-      memcpy(ptr2, ptr, len);
-      ptr2[len]='\0';
-      av_push(perl_get_av("fields", TRUE), newSVpvn(ptr2, len));
-      owl_free(ptr2);
-    }
-  }
-
-  /* run the procedure corresponding to the mode */
-  sprintf(runstr, "%s();", funcname);
-  return(owl_config_execute(runstr));
-}
-
Index: style.c
===================================================================
--- style.c	(revision ef56a6724cbce9cfe55d35d4b300df48c8c464c6)
+++ style.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -3,17 +3,28 @@
 static const char fileIdent[] = "$Id$";
 
-void owl_style_create_internal(owl_style *s, char *name, void (*formatfunc) (owl_fmtext *fm, owl_message *m))
+void owl_style_create_internal(owl_style *s, char *name, void (*formatfunc) (owl_fmtext *fm, owl_message *m), char *description)
 {
   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)
+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;
 }
@@ -30,4 +41,9 @@
 }
 
+char *owl_style_get_description(owl_style *s)
+{
+  return(s->description);
+}
+
 /* Use style 's' to format message 'm' into fmtext 'fm'.
  * 'fm' should already be be initialzed
@@ -41,5 +57,5 @@
 
     /* run the perl function */
-    body=owl_config_getmsg(m, s->perlfuncname);
+    body=owl_perlconfig_getmsg(m, 1, s->perlfuncname);
     
     /* indent */
@@ -55,7 +71,22 @@
 }
 
+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 {
+    return -1;
+  }
+}
+
 void owl_style_free(owl_style *s)
 {
   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);
Index: util.c
===================================================================
--- util.c	(revision 3ba3af00ede219be9bf18197463a48d3b5dd9d37)
+++ util.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -283,5 +283,5 @@
 char *owl_util_minutes_to_timestr(int in)
 {
-  int days, minutes, hours;
+  int days, hours;
   long run;
   char *out;
Index: variable.c
===================================================================
--- variable.c	(revision 09489b896891e6c4e2b0a2a7d622c25749410cf1)
+++ variable.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -204,7 +204,14 @@
   OWLVAR_STRING( "default_style" /* %OwlVarStub */, "default",
 		 "name of the default formatting style",
-		 "This sets the default message formatting style. Possbile\n"
-		 "values include 'default' 'basic' 'oneline' and if\n"
-		 "available, 'perl'\n" ),
+		 "This sets the default message formatting style.\n"
+		 "Styles may be created with the 'style' command.\n"
+		 "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"
+		 "\nSEE ALSO: style, show styles, view -s <style>\n"
+		 ),
+
 
   OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
@@ -356,23 +363,4 @@
   owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
   return(owl_variable_string_set_default(v, newval));
-}
-
-int owl_variable_style_set(owl_variable *v, void *newval) {
-  /* Invalidate all message formats first */
-  int ret;
-  owl_style *s;
-
-  s=owl_global_get_style_by_name(&g, newval);
-  if (!s) {
-    /* this message won't get seen, we'll need to deal with that later */
-    owl_function_makemsg("No style named '%s' exists.", newval);
-    return(0);
-  }
-  
-  owl_messagelist_invalidate_formats(owl_global_get_msglist(&g));
-  ret=owl_variable_string_set_default(v, newval);
-  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
-  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-  return(ret);
 }
 
Index: view.c
===================================================================
--- view.c	(revision ef56a6724cbce9cfe55d35d4b300df48c8c464c6)
+++ view.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -67,4 +67,8 @@
 {
   return(v->style);
+}
+
+char *owl_view_get_style_name(owl_view *v) {
+  return(owl_style_get_name(v->style));
 }
 
Index: zephyr.c
===================================================================
--- zephyr.c	(revision e6449bc3713fa8e0d1af7b15ef39089c748ae567)
+++ zephyr.c	(revision f1e629de3f6889c21f5f9dd7225e11c4fe9408b4)
@@ -731,5 +731,4 @@
 #endif
 
-
 /* returns a buffer of subscriptions or an error message.
  * Caller must free the return.
