Index: ChangeLog
===================================================================
--- ChangeLog	(revision 6e056552ea175d120128f2386dbb648d2df17912)
+++ ChangeLog	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -1,4 +1,11 @@
 $Id$
 
+2.0.4-pre-1
+	Make command line option -n actualy work
+
+	'set style' now works.  Possbile values at the moment are
+	   'default' 'basic' or 'perl', but the last only if a
+	   format_msg() function is found in .owlconf
+	
 2.0.3
 	Don't ring the terminal bell on mail messages.
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 6a415e91912b4795a141097f08a02c8a3229a908)
+++ Makefile.in	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -23,5 +23,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 buddylist.c timer.c
+     aim.c buddylist.c timer.c style.c stylefunc.c
 OWL_SRC = owl.c
 TESTER_SRC = tester.c
Index: buddylist.c
===================================================================
--- buddylist.c	(revision b2b077340663beb07545909f5ec5e8c55b61911d)
+++ buddylist.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -1,3 +1,5 @@
 #include "owl.h"
+
+static const char fileIdent[] = "$Id$";
 
 void owl_buddylist_init(owl_buddylist *b)
Index: fmtext.c
===================================================================
--- fmtext.c	(revision 6bf73cecd2de0409b50cad3b03d21e208f546137)
+++ fmtext.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -468,5 +468,5 @@
   for (i=0; i<lines; i++) {
     offset=ptr1-in->textbuff;
-    ptr2=strchr(ptr1, '\n'); /* this is a valgrind suspicious line */
+    ptr2=strchr(ptr1, '\n');
     if (!ptr2) {
       _owl_fmtext_append_fmtext(out, in, offset, (in->textlen)-1);
@@ -578,5 +578,5 @@
   }
   dst->textlen=src->textlen;
-  dst->textbuff=owl_malloc(mallocsize); /* valgrind suspcious line */
+  dst->textbuff=owl_malloc(mallocsize);
   dst->fmbuff=owl_malloc(mallocsize);
   dst->colorbuff=owl_malloc(mallocsize);
Index: global.c
===================================================================
--- global.c	(revision 6a415e91912b4795a141097f08a02c8a3229a908)
+++ global.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -52,4 +52,5 @@
   owl_list_create(&(g->puntlist));
   owl_list_create(&(g->messagequeue));
+  owl_list_create(&(g->stylelist));
   g->curmsg_vert_offset=0;
   g->resizepending=0;
@@ -728,2 +729,28 @@
 }
   
+/* style */
+
+/* Return the style with name 'name'.  If it does not exist return
+ * NULL */
+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);
+}
+
+owl_style *owl_global_get_current_style(owl_global *g) {
+  return(owl_global_get_style_by_name(g, owl_global_get_style(g)));
+}
+
+void owl_global_add_style(owl_global *g, owl_style *s) {
+  owl_list_append_element(&(g->stylelist), s);
+}
Index: message.c
===================================================================
--- message.c	(revision d559df97bd8fe22559fdadb8b64e5166521fa4b2)
+++ message.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -24,4 +24,5 @@
   strcpy(m->hostname, "");
   m->zwriteline=strdup("");
+  m->invalid_format=1;
 
   owl_list_create(&(m->attributes));
@@ -31,4 +32,5 @@
   m->time=owl_strdup(ctime(&t));
   m->time[strlen(m->time)-1]='\0';
+  owl_fmtext_init_null(&(m->fmtext));
 }
 
@@ -98,6 +100,23 @@
 }
 
+void owl_message_invalidate_format(owl_message *m)
+{
+  m->invalid_format=1;
+}
+
 owl_fmtext *owl_message_get_fmtext(owl_message *m)
 {
+  owl_style *s;
+
+  /* if the format is invalid, regenerate the text based on the
+   * current style
+   */
+  if (m->invalid_format) {
+    owl_fmtext_free(&(m->fmtext));
+    owl_fmtext_init_null(&(m->fmtext));
+    s=owl_global_get_current_style(&g);
+    owl_style_get_formattext(s, &(m->fmtext), m);
+    m->invalid_format=0;
+  }
   return(&(m->fmtext));
 }
@@ -371,4 +390,5 @@
 {
   if (m == NULL) return(0);
+  (void) owl_message_get_fmtext(m);
   return(owl_fmtext_num_lines(&(m->fmtext)));
 }
@@ -417,4 +437,7 @@
 {
   owl_fmtext a, b;
+
+  /* this will ensure that our cached copy is up to date */
+  (void) owl_message_get_fmtext(m);
 
   owl_fmtext_init_null(&a);
@@ -538,33 +561,16 @@
   return(m->id);
 }
-					
+
+/* return 1 if the message contains "string", 0 otherwise.  This is
+ * case insensitive because the functions it uses are
+ */
 int owl_message_search(owl_message *m, char *string)
 {
-  /* return 1 if the message contains "string", 0 otherwise.  This is
-   * case insensitive because the functions it uses are */
-
+
+  (void) owl_message_get_fmtext(m); /* is this necessary? */
+  
   return (owl_fmtext_search(&(m->fmtext), string));
 }
 
-void owl_message_create(owl_message *m, char *header, char *text)
-{
-  char *indent;
-
-  owl_message_init(m);
-  owl_message_set_body(m, text);
-
-  indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
-  owl_text_indent(indent, text, OWL_MSGTAB);
-  owl_fmtext_init_null(&(m->fmtext));
-  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-  owl_fmtext_append_ztext(&(m->fmtext), header);
-  owl_fmtext_append_normal(&(m->fmtext), "\n");
-  owl_fmtext_append_ztext(&(m->fmtext), indent);
-  if (text[strlen(text)-1]!='\n') {
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  }
-
-  owl_free(indent);
-}
 
 /* if loginout == -1 it's a logout message
@@ -596,81 +602,12 @@
     owl_message_set_islogin(m);
   }
-
-  /* create the formatted message */
-  if (owl_global_is_config_format(&g)) {
-    _owl_message_make_text_from_config(m);
-  } else {
-    _owl_message_make_text_from_aim(m);
-  }
-}
-
-void _owl_message_make_text_from_aim(owl_message *m)
-{
-  char *indent;
-
-  if (owl_message_is_loginout(m)) {
-    owl_fmtext_init_null(&(m->fmtext));
-    owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-    if (owl_message_is_login(m)) {
-      owl_fmtext_append_bold(&(m->fmtext), "AIM LOGIN");
-    } else {
-      owl_fmtext_append_bold(&(m->fmtext), "AIM LOGOUT");
-    }
-    owl_fmtext_append_normal(&(m->fmtext), " for ");
-    owl_fmtext_append_normal(&(m->fmtext), owl_message_get_sender(m));
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  } else if (owl_message_is_direction_in(m)) {
-    indent=owl_malloc(strlen(owl_message_get_body(m))+owl_text_num_lines(owl_message_get_body(m))*OWL_MSGTAB+10);
-    owl_text_indent(indent, owl_message_get_body(m), OWL_MSGTAB);
-    owl_fmtext_init_null(&(m->fmtext));
-    owl_fmtext_append_bold(&(m->fmtext), OWL_TABSTR);
-    owl_fmtext_append_bold(&(m->fmtext), "AIM from ");
-    owl_fmtext_append_bold(&(m->fmtext), owl_message_get_sender(m));
-    owl_fmtext_append_bold(&(m->fmtext), "\n");
-    owl_fmtext_append_bold(&(m->fmtext), indent);
-    if (indent[strlen(indent)-1]!='\n') {
-      owl_fmtext_append_normal(&(m->fmtext), "\n");
-    }
-    owl_free(indent);
-  } else if (owl_message_is_direction_out(m)) {
-    indent=owl_malloc(strlen(owl_message_get_body(m))+owl_text_num_lines(owl_message_get_body(m))*OWL_MSGTAB+10);
-    owl_text_indent(indent, owl_message_get_body(m), OWL_MSGTAB);
-    owl_fmtext_init_null(&(m->fmtext));
-    owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-    owl_fmtext_append_normal(&(m->fmtext), "AIM sent to ");
-    owl_fmtext_append_normal(&(m->fmtext), owl_message_get_recipient(m));
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-    owl_fmtext_append_ztext(&(m->fmtext), indent);
-    if (indent[strlen(indent)-1]!='\n') {
-      owl_fmtext_append_normal(&(m->fmtext), "\n");
-    }
-    owl_free(indent);
-  }
 }
 
 void owl_message_create_admin(owl_message *m, char *header, char *text)
 {
-  char *indent;
-
   owl_message_init(m);
   owl_message_set_type_admin(m);
-
   owl_message_set_body(m, text);
-
-  /* do something to make it clear the notice shouldn't be used for now */
-
-  indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
-  owl_text_indent(indent, text, OWL_MSGTAB);
-  owl_fmtext_init_null(&(m->fmtext));
-  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-  owl_fmtext_append_bold(&(m->fmtext), "OWL ADMIN ");
-  owl_fmtext_append_ztext(&(m->fmtext), header);
-  owl_fmtext_append_normal(&(m->fmtext), "\n");
-  owl_fmtext_append_ztext(&(m->fmtext), indent);
-  if (text[strlen(text)-1]!='\n') {
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  }
-
-  owl_free(indent);
+  owl_message_set_attribute(m, "adminheader", header); /* just a hack for now */
 }
 
@@ -770,14 +707,4 @@
   m->time=owl_strdup(ctime((time_t *) &n->z_time.tv_sec));
   m->time[strlen(m->time)-1]='\0';
-
-  /* create the formatted message */
-  if (owl_global_is_config_format(&g)) {
-    _owl_message_make_text_from_config(m);
-  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
-    _owl_message_make_text_from_notice_standard(m);
-  } else {
-    _owl_message_make_text_from_notice_simple(m);
-  }
-
 }
 
@@ -812,300 +739,7 @@
   }
 
-  /* create the formatted message */
-  if (owl_global_is_config_format(&g)) {
-    _owl_message_make_text_from_config(m);
-  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
-    _owl_message_make_text_from_zwriteline_standard(m);
-  } else {
-    _owl_message_make_text_from_zwriteline_simple(m);
-  }
-
   owl_zwrite_free(&z);
 }
 
-void _owl_message_make_text_from_config(owl_message *m)
-{
-  char *body, *indent;
-
-  owl_fmtext_init_null(&(m->fmtext));
-
-  /* get body from the config */
-  body=owl_config_getmsg(m, 1);
-  
-  /* indent */
-  indent=owl_malloc(strlen(body)+owl_text_num_lines(body)*OWL_TAB+10);
-  owl_text_indent(indent, body, OWL_TAB);
-
-  /* fmtext_append.  This needs to change */
-  owl_fmtext_append_ztext(&(m->fmtext), indent);
-
-  owl_free(indent);
-  owl_free(body);
-}
-
-void _owl_message_make_text_from_zwriteline_standard(owl_message *m)
-{
-  char *indent, *text, *zsigbuff, *foo;
-
-  text=owl_message_get_body(m);
-
-  indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
-  owl_text_indent(indent, text, OWL_MSGTAB);
-  owl_fmtext_init_null(&(m->fmtext));
-  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-  owl_fmtext_append_normal(&(m->fmtext), "Zephyr sent to ");
-  foo=short_zuser(owl_message_get_recipient(m));
-  owl_fmtext_append_normal(&(m->fmtext), foo);
-  owl_free(foo);
-  owl_fmtext_append_normal(&(m->fmtext), "  (Zsig: ");
-
-  zsigbuff=owl_malloc(strlen(owl_message_get_zsig(m))+30);
-  owl_message_pretty_zsig(m, zsigbuff);
-  owl_fmtext_append_ztext(&(m->fmtext), zsigbuff);
-  owl_free(zsigbuff);
-  
-  owl_fmtext_append_normal(&(m->fmtext), ")");
-  owl_fmtext_append_normal(&(m->fmtext), "\n");
-  owl_fmtext_append_ztext(&(m->fmtext), indent);
-  if (text[strlen(text)-1]!='\n') {
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  }
-
-  owl_free(indent);
-}
-
-void _owl_message_make_text_from_zwriteline_simple(owl_message *m)
-{
-  char *indent, *text, *zsigbuff, *foo;
-
-  text=owl_message_get_body(m);
-
-  indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
-  owl_text_indent(indent, text, OWL_MSGTAB);
-  owl_fmtext_init_null(&(m->fmtext));
-  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-  owl_fmtext_append_normal(&(m->fmtext), "To: ");
-  foo=short_zuser(owl_message_get_recipient(m));
-  owl_fmtext_append_normal(&(m->fmtext), foo);
-  owl_free(foo);
-  owl_fmtext_append_normal(&(m->fmtext), "  (Zsig: ");
-
-  zsigbuff=owl_malloc(strlen(owl_message_get_zsig(m))+30);
-  owl_message_pretty_zsig(m, zsigbuff);
-  owl_fmtext_append_ztext(&(m->fmtext), zsigbuff);
-  owl_free(zsigbuff);
-  
-  owl_fmtext_append_normal(&(m->fmtext), ")");
-  owl_fmtext_append_normal(&(m->fmtext), "\n");
-  owl_fmtext_append_ztext(&(m->fmtext), indent);
-  if (text[strlen(text)-1]!='\n') {
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  }
-
-  owl_free(indent);
-}
-
-void _owl_message_make_text_from_notice_standard(owl_message *m)
-{
-  char *body, *indent, *ptr, *zsigbuff, frombuff[LINE];
-  ZNotice_t *n;
-
-  n=&(m->notice);
-  
-  /* get the body */
-  body=owl_malloc(strlen(owl_message_get_body(m))+30);
-  strcpy(body, owl_message_get_body(m));
-
-  /* add a newline if we need to */
-  if (body[0]!='\0' && body[strlen(body)-1]!='\n') {
-    strcat(body, "\n");
-  }
-
-  /* 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);
-
-  /* edit the from addr for printing */
-  strcpy(frombuff, owl_message_get_sender(m));
-  ptr=strchr(frombuff, '@');
-  if (ptr && !strncmp(ptr+1, ZGetRealm(), strlen(ZGetRealm()))) {
-    *ptr='\0';
-  }
-
-  /* set the message for printing */
-  owl_fmtext_init_null(&(m->fmtext));
-  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-
-  if (!strcasecmp(owl_message_get_opcode(m), "ping") && owl_message_is_private(m)) {
-    owl_fmtext_append_bold(&(m->fmtext), "PING");
-    owl_fmtext_append_normal(&(m->fmtext), " from ");
-    owl_fmtext_append_bold(&(m->fmtext), frombuff);
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  } else if (!strcasecmp(n->z_class, "login")) {
-    char *ptr, host[LINE], tty[LINE];
-    int len;
-
-    ptr=owl_zephyr_get_field(n, 1, &len);
-    strncpy(host, ptr, len);
-    host[len]='\0';
-    ptr=owl_zephyr_get_field(n, 3, &len);
-    strncpy(tty, ptr, len);
-    tty[len]='\0';
-    
-    if (!strcasecmp(n->z_opcode, "user_login")) {
-      owl_fmtext_append_bold(&(m->fmtext), "LOGIN");
-    } else if (!strcasecmp(n->z_opcode, "user_logout")) {
-      owl_fmtext_append_bold(&(m->fmtext), "LOGOUT");
-    }
-    owl_fmtext_append_normal(&(m->fmtext), " for ");
-    ptr=short_zuser(n->z_class_inst);
-    owl_fmtext_append_bold(&(m->fmtext), ptr);
-    owl_free(ptr);
-    owl_fmtext_append_normal(&(m->fmtext), " at ");
-    owl_fmtext_append_normal(&(m->fmtext), host);
-    owl_fmtext_append_normal(&(m->fmtext), " ");
-    owl_fmtext_append_normal(&(m->fmtext), tty);
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  } else {
-    owl_fmtext_append_normal(&(m->fmtext), owl_message_get_class(m));
-    owl_fmtext_append_normal(&(m->fmtext), " / ");
-    owl_fmtext_append_normal(&(m->fmtext), owl_message_get_instance(m));
-    owl_fmtext_append_normal(&(m->fmtext), " / ");
-    owl_fmtext_append_bold(&(m->fmtext), frombuff);
-    if (strcasecmp(owl_message_get_realm(m), ZGetRealm())) {
-      owl_fmtext_append_normal(&(m->fmtext), " {");
-      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_realm(m));
-      owl_fmtext_append_normal(&(m->fmtext), "} ");
-    }
-    if (n->z_opcode[0]!='\0') {
-      owl_fmtext_append_normal(&(m->fmtext), " [");
-      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_opcode(m));
-      owl_fmtext_append_normal(&(m->fmtext), "] ");
-    }
-
-    /* stick on the zsig */
-    zsigbuff=owl_malloc(strlen(owl_message_get_zsig(m))+30);
-    owl_message_pretty_zsig(m, zsigbuff);
-    owl_fmtext_append_normal(&(m->fmtext), "    (");
-    owl_fmtext_append_ztext(&(m->fmtext), zsigbuff);
-    owl_fmtext_append_normal(&(m->fmtext), ")");
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-    owl_free(zsigbuff);
-
-    /* then the indented message */
-    owl_fmtext_append_ztext(&(m->fmtext), indent);
-
-    /* make private messages bold for smaat users */
-    if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
-      if (owl_message_is_personal(m)) {
-	owl_fmtext_addattr((&m->fmtext), OWL_FMTEXT_ATTR_BOLD);
-      }
-    }
-  }
-
-  owl_free(body);
-  owl_free(indent);
-}
-
-void _owl_message_make_text_from_notice_simple(owl_message *m)
-{
-  char *body, *indent, *ptr, *zsigbuff, frombuff[LINE];
-  ZNotice_t *n;
-
-  n=&(m->notice);
-
-  /* get the body */
-  body=owl_strdup(owl_message_get_body(m));
-  body=realloc(body, strlen(body)+30);
-
-  /* add a newline if we need to */
-  if (body[0]!='\0' && body[strlen(body)-1]!='\n') {
-    strcat(body, "\n");
-  }
-
-  /* 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);
-
-  /* edit the from addr for printing */
-  strcpy(frombuff, owl_message_get_sender(m));
-  ptr=strchr(frombuff, '@');
-  if (ptr && !strncmp(ptr+1, ZGetRealm(), strlen(ZGetRealm()))) {
-    *ptr='\0';
-  }
-
-  /* set the message for printing */
-  owl_fmtext_init_null(&(m->fmtext));
-  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
-
-  if (!strcasecmp(owl_message_get_opcode(m), "ping")) {
-    owl_fmtext_append_bold(&(m->fmtext), "PING");
-    owl_fmtext_append_normal(&(m->fmtext), " from ");
-    owl_fmtext_append_bold(&(m->fmtext), frombuff);
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  } else if (!strcasecmp(owl_message_get_class(m), "login")) {
-    char *ptr, host[LINE], tty[LINE];
-    int len;
-
-    ptr=owl_zephyr_get_field(n, 1, &len);
-    strncpy(host, ptr, len);
-    host[len]='\0';
-    ptr=owl_zephyr_get_field(n, 3, &len);
-    strncpy(tty, ptr, len);
-    tty[len]='\0';
-    
-    if (!strcasecmp(owl_message_get_opcode(m), "user_login")) {
-      owl_fmtext_append_bold(&(m->fmtext), "LOGIN");
-    } else if (!strcasecmp(owl_message_get_opcode(m), "user_logout")) {
-      owl_fmtext_append_bold(&(m->fmtext), "LOGOUT");
-    }
-    owl_fmtext_append_normal(&(m->fmtext), " for ");
-    ptr=short_zuser(owl_message_get_instance(m));
-    owl_fmtext_append_bold(&(m->fmtext), ptr);
-    owl_free(ptr);
-    owl_fmtext_append_normal(&(m->fmtext), " at ");
-    owl_fmtext_append_normal(&(m->fmtext), host);
-    owl_fmtext_append_normal(&(m->fmtext), " ");
-    owl_fmtext_append_normal(&(m->fmtext), tty);
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-  } else {
-    owl_fmtext_append_normal(&(m->fmtext), "From: ");
-    if (strcasecmp(owl_message_get_class(m), "message")) {
-      owl_fmtext_append_normal(&(m->fmtext), "Class ");
-      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_class(m));
-      owl_fmtext_append_normal(&(m->fmtext), " / Instance ");
-      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_instance(m));
-      owl_fmtext_append_normal(&(m->fmtext), " / ");
-    }
-    owl_fmtext_append_normal(&(m->fmtext), frombuff);
-    if (strcasecmp(owl_message_get_realm(m), ZGetRealm())) {
-      owl_fmtext_append_normal(&(m->fmtext), " {");
-      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_realm(m));
-      owl_fmtext_append_normal(&(m->fmtext), "} ");
-    }
-
-    /* stick on the zsig */
-    zsigbuff=owl_malloc(strlen(owl_message_get_zsig(m))+30);
-    owl_message_pretty_zsig(m, zsigbuff);
-    owl_fmtext_append_normal(&(m->fmtext), "    (");
-    owl_fmtext_append_ztext(&(m->fmtext), zsigbuff);
-    owl_fmtext_append_normal(&(m->fmtext), ")");
-    owl_fmtext_append_normal(&(m->fmtext), "\n");
-    owl_free(zsigbuff);
-
-    /* then the indented message */
-    owl_fmtext_append_ztext(&(m->fmtext), indent);
-
-    /* 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((&m->fmtext), OWL_FMTEXT_ATTR_BOLD);
-      }
-    }
-  }
-
-  owl_free(body);
-  owl_free(indent);
-}
 
 void owl_message_pretty_zsig(owl_message *m, char *buff)
Index: messagelist.c
===================================================================
--- messagelist.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ messagelist.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -5,18 +5,22 @@
 static const char fileIdent[] = "$Id$";
 
-int owl_messagelist_create(owl_messagelist *ml) {
+int owl_messagelist_create(owl_messagelist *ml)
+{
   owl_list_create(&(ml->list));
   return(0);
 }
 
-int owl_messagelist_get_size(owl_messagelist *ml) {
+int owl_messagelist_get_size(owl_messagelist *ml)
+{
   return(owl_list_get_size(&(ml->list)));
 }
 
-void *owl_messagelist_get_element(owl_messagelist *ml, int n) {
+void *owl_messagelist_get_element(owl_messagelist *ml, int n)
+{
   return(owl_list_get_element(&(ml->list), n));
 }
 
-owl_message *owl_messagelist_get_by_id(owl_messagelist *ml, int id) {
+owl_message *owl_messagelist_get_by_id(owl_messagelist *ml, int id)
+{
   /* return the message with id == 'id'.  If it doesn't exist return NULL. */
   /* we could make this much more efficient at some point */
@@ -36,10 +40,12 @@
 }
 
-int owl_messagelist_append_element(owl_messagelist *ml, void *element) {
+int owl_messagelist_append_element(owl_messagelist *ml, void *element)
+{
   return(owl_list_append_element(&(ml->list), element));
 }
 
 /* do we really still want this? */
-int owl_messagelist_delete_element(owl_messagelist *ml, int n) {
+int owl_messagelist_delete_element(owl_messagelist *ml, int n)
+{
   /* mark a message as deleted */
   owl_message_mark_delete(owl_list_get_element(&(ml->list), n));
@@ -47,5 +53,6 @@
 }
 
-int owl_messagelist_undelete_element(owl_messagelist *ml, int n) {
+int owl_messagelist_undelete_element(owl_messagelist *ml, int n)
+{
   /* mark a message as deleted */
   owl_message_unmark_delete(owl_list_get_element(&(ml->list), n));
@@ -53,5 +60,6 @@
 }
 
-int owl_messagelist_expunge(owl_messagelist *ml) {
+int owl_messagelist_expunge(owl_messagelist *ml)
+{
   /* expunge deleted messages */
   int i, j;
@@ -79,2 +87,14 @@
   return(0);
 }
+
+void owl_messagelist_invalidate_formats(owl_messagelist *ml)
+{
+  int i, j;
+  owl_message *m;
+
+  j=owl_list_get_size(&(ml->list));
+  for (i=0; i<j; i++) {
+    m=owl_list_get_element(&(ml->list), i);
+    owl_message_invalidate_format(m);
+  }
+}
Index: owl.c
===================================================================
--- owl.c	(revision 6bf73cecd2de0409b50cad3b03d21e208f546137)
+++ owl.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -37,4 +37,5 @@
   char *configfile, *tty, *perlout, **argvsave, buff[LINE], startupmsg[LINE];
   owl_filter *f;
+  owl_style *s;
   time_t nexttime, now;
   struct tm *today;
@@ -46,4 +47,5 @@
   tty=NULL;
   debug=0;
+  initialsubs=1;
   if (argc>0) {
     argv++;
@@ -128,5 +130,5 @@
 
     
-  /* owl init */
+  /* owl global init */
   owl_global_init(&g);
   if (debug) owl_global_set_debug_on(&g);
@@ -145,8 +147,17 @@
   }
 
+  /* setup the built-in styles */
+  s=owl_malloc(sizeof(owl_style));
+  owl_style_create_internal(s, "default", &owl_stylefunc_default);
+  owl_global_add_style(&g, s);
+
+  s=owl_malloc(sizeof(owl_style));
+  owl_style_create_internal(s, "basic", &owl_stylefunc_basic);
+  owl_global_add_style(&g, s);
+
   /* setup the default filters */
   /* the personal filter will need to change again when AIM chat's are
    *  included.  Also, there should be an %aimme% */
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "personal", "( type ^zephyr$ "
 			     "and class ^message$ and instance ^personal$ "
@@ -155,41 +166,41 @@
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "trash", "class ^mail$ or opcode ^ping$ or type ^admin$ or class ^login$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "ping", "opcode ^ping$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "auto", "opcode ^auto$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "login", "class ^login$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "reply-lockout", "class ^noc or class ^mail$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "out", "direction ^out$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "aim", "type ^aim$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "zephyr", "type ^zephyr$");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "none", "false");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
 
-  f=malloc(sizeof(owl_filter));
+  f=owl_malloc(sizeof(owl_filter));
   owl_filter_init_fromstring(f, "all", "true");
   owl_list_append_element(owl_global_get_filterlist(&g), f);
@@ -211,4 +222,12 @@
     printf("\nError parsing configfile\n");
     exit(1);
+  }
+
+  /* if the config defaults a formatting function, add 'perl' as a style */
+  if (owl_global_is_config_format(&g)) {
+    owl_function_debugmsg("Found perl formatting");
+    s=owl_malloc(sizeof(owl_style));
+    owl_style_create_perl(s, "perl", "owl::format_msg");
+    owl_global_add_style(&g, s);
   }
 
@@ -228,12 +247,15 @@
 
   /* load zephyr subs */
-  ret=owl_zephyr_loadsubs(NULL);
-  if (ret!=-1) {
-    owl_global_add_userclue(&g, OWL_USERCLUE_CLASSES);
-  }
-
-  /* load login subs */
-  if (owl_global_is_loginsubs(&g)) {
-    owl_function_loadloginsubs(NULL);
+  if (initialsubs) {
+    /* load normal subscriptions */
+    ret=owl_zephyr_loadsubs(NULL);
+    if (ret!=-1) {
+      owl_global_add_userclue(&g, OWL_USERCLUE_CLASSES);
+    }
+
+    /* load login subscriptions */
+    if (owl_global_is_loginsubs(&g)) {
+      owl_function_loadloginsubs(NULL);
+    }
   }
 
@@ -241,4 +263,14 @@
   if (owl_global_is_startuplogin(&g)) {
     owl_zephyr_zlog_in();
+  }
+
+  /* set the default style, based on userclue and presence of a
+   *  formatting function */
+  if (owl_global_is_config_format(&g)) {
+    owl_global_set_style(&g, "perl");
+  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
+    owl_global_set_style(&g, "default");
+  } else {
+    owl_global_set_style(&g, "basic");
   }
 
@@ -275,5 +307,4 @@
 
     followlast=owl_global_should_followlast(&g);
-
     
     /* If we're logged into AIM, do AIM stuff */
@@ -306,5 +337,6 @@
       owl_message *m;
       owl_filter *f;
-
+      
+      /* grab the new message, stick it in 'm' */
       if (ZPending()) {
 	/* grab a zephyr notice, but if we've done 20 without stopping,
@@ -332,5 +364,5 @@
       }
       
-      /* if it's on the puntlist then, nuke it and continue */
+      /* if this message it on the puntlist, nuke it and continue */
       if (owl_global_message_is_puntable(&g, m)) {
 	owl_message_free(m);
@@ -343,5 +375,5 @@
 
       /* let the config know the new message has been received */
-      owl_config_getmsg(m, 0);
+      owl_config_getmsg(m, "owl::receive_msg();");
 
       /* add it to any necessary views; right now there's only the current view */
@@ -432,8 +464,7 @@
     }
 
-    /* Handle all keypresses.
-     * If no key has been pressed sleep for a little bit, but
-     * otherwise do not, this lets input be grabbed as quickly
-     * as possbile */
+    /* Handle all keypresses.  If no key has been pressed, sleep for a
+     * little bit, but otherwise do not.  This lets input be grabbed
+     * as quickly as possbile */
     j=wgetch(typwin);
     if (j==ERR) {
@@ -471,5 +502,7 @@
 void sig_handler(int sig) {
   if (sig==SIGWINCH) {
-    /* we can't inturrupt a malloc here, so it just sets a flag */
+    /* we can't inturrupt a malloc here, so it just sets a flag
+     * schedulding a resize for later
+     */
     owl_function_resize();
   }
Index: owl.h
===================================================================
--- owl.h	(revision 6e056552ea175d120128f2386dbb648d2df17912)
+++ owl.h	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -14,11 +14,11 @@
 static const char owl_h_fileIdent[] = "$Id$";
 
-#define OWL_VERSION         2.0.3
-#define OWL_VERSION_STRING "2.0.3"
+#define OWL_VERSION         2.0.4-pre-1
+#define OWL_VERSION_STRING "2.0.4-pre-1"
 
 #define OWL_DEBUG 0
 #define OWL_DEBUG_FILE "/var/tmp/owldebug"
 
-#define OWL_CONFIG_DIR "/.owl"           /* this is relative to the user's home directory */
+#define OWL_CONFIG_DIR "/.owl"             /* this is relative to the user's home directory */
 #define OWL_STARTUP_FILE "/.owl/startup"   /* this is relative to the user's home directory */
 
@@ -64,4 +64,7 @@
 #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 */
@@ -245,5 +248,6 @@
   int direction;
   ZNotice_t notice;
-  owl_fmtext fmtext;
+  owl_fmtext fmtext;              /* this is now only a CACHED copy */
+  int invalid_format;             /* indicates whether fmtext needs to be regenerated */
   int delete;
   char hostname[MAXHOSTNAMELEN+1];
@@ -252,4 +256,11 @@
   char *zwriteline;
 } owl_message;
+
+typedef struct _owl_style {
+  char *name;
+  int type;
+  char *perlfuncname;
+  void (*formatfunc) (owl_fmtext *fm, owl_message *m);
+} owl_style;
 
 typedef struct _owl_mainwin {
@@ -415,8 +426,9 @@
   owl_timer aim_noop_timer;
   owl_timer aim_ignorelogin_timer;
-  int aim_loggedin;
-  char *aim_screenname;
-  owl_buddylist buddylist;
-  owl_list messagequeue; /* for queueing up aim and other messages */
+  int aim_loggedin;         /* true if currently logged into AIM */
+  char *aim_screenname;     /* currently logged in AIM screen name */
+  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_global;
 
Index: readconfig.c
===================================================================
--- readconfig.c	(revision d559df97bd8fe22559fdadb8b64e5166521fa4b2)
+++ readconfig.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -131,14 +131,8 @@
 }
 
-char *owl_config_getmsg(owl_message *m, int mode) {
-  /* 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.
-  */
-
+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("");
@@ -236,11 +230,6 @@
 
   /* run the procedure corresponding to the mode */
-  if (mode==1) {
-    return(owl_config_execute("owl::format_msg();"));
-  } else {
-    ptr=owl_config_execute("owl::receive_msg();");
-    if (ptr) owl_free(ptr);
-    return(NULL);
-  }
-}
-
+  sprintf(runstr, "%s();", funcname);
+  return(owl_config_execute(runstr));
+}
+
Index: style.c
===================================================================
--- style.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
+++ style.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -0,0 +1,60 @@
+#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))
+{
+  s->type=OWL_STYLE_TYPE_INTERNAL;
+  s->name=owl_strdup(name);
+  s->perlfuncname=NULL;
+  s->formatfunc=formatfunc;
+}
+
+void owl_style_create_perl(owl_style *s, char *name, char *perlfuncname)
+{
+  s->type=OWL_STYLE_TYPE_PERL;
+  s->name=owl_strdup(name);
+  s->perlfuncname=owl_strdup(perlfuncname);
+  s->formatfunc=NULL;
+}
+
+int owl_style_matches_name(owl_style *s, char *name)
+{
+  if (!strcmp(s->name, name)) return(1);
+  return(0);
+}
+
+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;
+
+    /* run the perl function */
+    body=owl_config_getmsg(m, s->perlfuncname);
+    
+    /* indent */
+    indent=owl_malloc(strlen(body)+owl_text_num_lines(body)*OWL_TAB+10);
+    owl_text_indent(indent, body, OWL_TAB);
+    
+    /* fmtext_append.  This needs to change */
+    owl_fmtext_append_ztext(fm, indent);
+    
+    owl_free(indent);
+    owl_free(body);
+  }
+}
+
+char *owl_style_get_name(owl_style *s)
+{
+  return(s->name);
+}
+
+void owl_style_free(owl_style *s)
+{
+  if (s->name) owl_free(s->name);
+  if (s->type==OWL_STYLE_TYPE_PERL && s->perlfuncname) {
+    owl_free(s->perlfuncname);
+  }
+}
Index: stylefunc.c
===================================================================
--- stylefunc.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
+++ stylefunc.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -0,0 +1,385 @@
+#include "owl.h"
+
+static const char fileIdent[] = "$Id$";
+
+void owl_stylefunc_basic(owl_fmtext *fm, owl_message *m)
+{
+  char *body, *indent, *ptr, *zsigbuff, frombuff[LINE];
+  ZNotice_t *n;
+
+  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
+    n=owl_message_get_notice(m);
+
+    /* get the body */
+    body=owl_strdup(owl_message_get_body(m));
+    body=realloc(body, strlen(body)+30);
+
+    /* add a newline if we need to */
+    if (body[0]!='\0' && body[strlen(body)-1]!='\n') {
+      strcat(body, "\n");
+    }
+    
+    /* 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);
+    
+    /* edit the from addr for printing */
+    strcpy(frombuff, owl_message_get_sender(m));
+    ptr=strchr(frombuff, '@');
+    if (ptr && !strncmp(ptr+1, ZGetRealm(), strlen(ZGetRealm()))) {
+      *ptr='\0';
+    }
+    
+    /* set the message for printing */
+    owl_fmtext_append_normal(fm, OWL_TABSTR);
+    
+    if (!strcasecmp(owl_message_get_opcode(m), "ping")) {
+      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 (!strcasecmp(owl_message_get_class(m), "login")) {
+      char *ptr, host[LINE], tty[LINE];
+      int len;
+      
+      ptr=owl_zephyr_get_field(n, 1, &len);
+      strncpy(host, ptr, len);
+      host[len]='\0';
+      ptr=owl_zephyr_get_field(n, 3, &len);
+      strncpy(tty, ptr, len);
+      tty[len]='\0';
+      
+      if (!strcasecmp(owl_message_get_opcode(m), "user_login")) {
+	owl_fmtext_append_bold(fm, "LOGIN");
+      } else if (!strcasecmp(owl_message_get_opcode(m), "user_logout")) {
+	owl_fmtext_append_bold(fm, "LOGOUT");
+      }
+      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);
+      owl_fmtext_append_normal(fm, " ");
+      owl_fmtext_append_normal(fm, 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), ZGetRealm())) {
+	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_fmtext_append_ztext(fm, indent);
+      
+      /* 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((&m->fmtext), OWL_FMTEXT_ATTR_BOLD);
+	}
+      }
+    }
+    
+    owl_free(body);
+    owl_free(indent);
+  } else if (owl_message_is_type_zephyr(m) && owl_message_is_direction_out(m)) {
+    char *indent, *text, *zsigbuff, *foo;
+      
+    text=owl_message_get_body(m);
+    
+    indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
+    owl_text_indent(indent, text, OWL_MSGTAB);
+    owl_fmtext_init_null(fm);
+    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_fmtext_append_ztext(fm, indent);
+    if (text[strlen(text)-1]!='\n') {
+      owl_fmtext_append_normal(fm, "\n");
+    }
+    
+    owl_free(indent);
+  } else if (owl_message_is_type_aim(m)) {
+    char *indent;
+    
+    if (owl_message_is_loginout(m)) {
+      owl_fmtext_init_null(fm);
+      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)) {
+      indent=owl_malloc(strlen(owl_message_get_body(m))+owl_text_num_lines(owl_message_get_body(m))*OWL_MSGTAB+10);
+      owl_text_indent(indent, owl_message_get_body(m), OWL_MSGTAB);
+      owl_fmtext_init_null(fm);
+      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_fmtext_append_bold(fm, indent);
+      if (indent[strlen(indent)-1]!='\n') {
+	owl_fmtext_append_normal(fm, "\n");
+      }
+      owl_free(indent);
+    } else if (owl_message_is_direction_out(m)) {
+      indent=owl_malloc(strlen(owl_message_get_body(m))+owl_text_num_lines(owl_message_get_body(m))*OWL_MSGTAB+10);
+      owl_text_indent(indent, owl_message_get_body(m), OWL_MSGTAB);
+      owl_fmtext_init_null(fm);
+      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_fmtext_append_ztext(fm, indent);
+      if (indent[strlen(indent)-1]!='\n') {
+	owl_fmtext_append_normal(fm, "\n");
+      }
+      owl_free(indent);
+    }
+  } else if (owl_message_is_type_admin(m)) {
+    char *text, *header, *indent;
+    
+    text=owl_message_get_body(m);
+    header=owl_message_get_attribute_value(m, "adminheader");
+    
+    indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
+    owl_text_indent(indent, text, OWL_MSGTAB);
+    owl_fmtext_init_null(fm);
+    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_fmtext_append_ztext(fm, indent);
+    if (text[strlen(text)-1]!='\n') {
+      owl_fmtext_append_normal(fm, "\n");
+    }
+    
+    owl_free(indent);
+  }
+}
+
+void owl_stylefunc_default(owl_fmtext *fm, owl_message *m)
+{
+  char *body, *indent, *ptr, *zsigbuff, frombuff[LINE];
+  ZNotice_t *n;
+
+  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
+    n=owl_message_get_notice(m);
+  
+    /* get the body */
+    body=owl_malloc(strlen(owl_message_get_body(m))+30);
+    strcpy(body, owl_message_get_body(m));
+    
+    /* add a newline if we need to */
+    if (body[0]!='\0' && body[strlen(body)-1]!='\n') {
+      strcat(body, "\n");
+    }
+    
+    /* 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);
+    
+    /* edit the from addr for printing */
+    strcpy(frombuff, owl_message_get_sender(m));
+    ptr=strchr(frombuff, '@');
+    if (ptr && !strncmp(ptr+1, ZGetRealm(), strlen(ZGetRealm()))) {
+      *ptr='\0';
+    }
+    
+    /* set the message for printing */
+    owl_fmtext_init_null(fm);
+    owl_fmtext_append_normal(fm, OWL_TABSTR);
+    
+    if (!strcasecmp(owl_message_get_opcode(m), "ping") && owl_message_is_private(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 (!strcasecmp(n->z_class, "login")) {
+      char *ptr, host[LINE], tty[LINE];
+      int len;
+      
+      ptr=owl_zephyr_get_field(n, 1, &len);
+      strncpy(host, ptr, len);
+      host[len]='\0';
+      ptr=owl_zephyr_get_field(n, 3, &len);
+      strncpy(tty, ptr, len);
+      tty[len]='\0';
+      
+      if (!strcasecmp(n->z_opcode, "user_login")) {
+	owl_fmtext_append_bold(fm, "LOGIN");
+      } else if (!strcasecmp(n->z_opcode, "user_logout")) {
+	owl_fmtext_append_bold(fm, "LOGOUT");
+      }
+      owl_fmtext_append_normal(fm, " for ");
+      ptr=short_zuser(n->z_class_inst);
+      owl_fmtext_append_bold(fm, ptr);
+      owl_free(ptr);
+      owl_fmtext_append_normal(fm, " at ");
+      owl_fmtext_append_normal(fm, host);
+      owl_fmtext_append_normal(fm, " ");
+      owl_fmtext_append_normal(fm, tty);
+      owl_fmtext_append_normal(fm, "\n");
+    } else {
+      owl_fmtext_append_normal(fm, owl_message_get_class(m));
+      owl_fmtext_append_normal(fm, " / ");
+      owl_fmtext_append_normal(fm, owl_message_get_instance(m));
+      owl_fmtext_append_normal(fm, " / ");
+      owl_fmtext_append_bold(fm, frombuff);
+      if (strcasecmp(owl_message_get_realm(m), ZGetRealm())) {
+	owl_fmtext_append_normal(fm, " {");
+	owl_fmtext_append_normal(fm, owl_message_get_realm(m));
+	owl_fmtext_append_normal(fm, "} ");
+      }
+      if (n->z_opcode[0]!='\0') {
+	owl_fmtext_append_normal(fm, " [");
+	owl_fmtext_append_normal(fm, owl_message_get_opcode(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_fmtext_append_ztext(fm, indent);
+      
+      /* make private messages bold for smaat users */
+      if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
+	if (owl_message_is_personal(m)) {
+	  owl_fmtext_addattr((&m->fmtext), OWL_FMTEXT_ATTR_BOLD);
+	}
+      }
+    }
+    
+    owl_free(body);
+    owl_free(indent);
+  } else if (owl_message_is_type_zephyr(m) && owl_message_is_direction_out(m)) {
+    char *indent, *text, *zsigbuff, *foo;
+    
+    text=owl_message_get_body(m);
+    
+    indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
+    owl_text_indent(indent, text, OWL_MSGTAB);
+    owl_fmtext_init_null(fm);
+    owl_fmtext_append_normal(fm, OWL_TABSTR);
+    owl_fmtext_append_normal(fm, "Zephyr sent 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_fmtext_append_ztext(fm, indent);
+    if (text[strlen(text)-1]!='\n') {
+      owl_fmtext_append_normal(fm, "\n");
+    }
+    
+    owl_free(indent);
+  } else if (owl_message_is_type_aim(m)) {
+    char *indent;
+    
+    if (owl_message_is_loginout(m)) {
+      owl_fmtext_init_null(fm);
+      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)) {
+      indent=owl_malloc(strlen(owl_message_get_body(m))+owl_text_num_lines(owl_message_get_body(m))*OWL_MSGTAB+10);
+      owl_text_indent(indent, owl_message_get_body(m), OWL_MSGTAB);
+      owl_fmtext_init_null(fm);
+      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_fmtext_append_bold(fm, indent);
+      if (indent[strlen(indent)-1]!='\n') {
+	owl_fmtext_append_normal(fm, "\n");
+      }
+      owl_free(indent);
+    } else if (owl_message_is_direction_out(m)) {
+      indent=owl_malloc(strlen(owl_message_get_body(m))+owl_text_num_lines(owl_message_get_body(m))*OWL_MSGTAB+10);
+      owl_text_indent(indent, owl_message_get_body(m), OWL_MSGTAB);
+      owl_fmtext_init_null(fm);
+      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_fmtext_append_ztext(fm, indent);
+      if (indent[strlen(indent)-1]!='\n') {
+	owl_fmtext_append_normal(fm, "\n");
+      }
+      owl_free(indent);
+    }
+  } else if (owl_message_is_type_admin(m)) {
+    char *text, *header, *indent;
+    
+    text=owl_message_get_body(m);
+    header=owl_message_get_attribute_value(m, "adminheader");
+    
+    indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
+    owl_text_indent(indent, text, OWL_MSGTAB);
+    owl_fmtext_init_null(fm);
+    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_fmtext_append_ztext(fm, indent);
+    if (text[strlen(text)-1]!='\n') {
+      owl_fmtext_append_normal(fm, "\n");
+    }
+    
+    owl_free(indent);
+  }
+}
Index: variable.c
===================================================================
--- variable.c	(revision 6a415e91912b4795a141097f08a02c8a3229a908)
+++ variable.c	(revision bd3f2322e69e72e9760505782651c29325f28b4b)
@@ -198,5 +198,8 @@
   OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
 		      NULL, owl_variable_tty_set, NULL),
-  
+
+  OWLVAR_STRING_FULL( "style" /* %OwlVarStub */, "default", "name of the current formatting style", "",
+		      NULL, owl_variable_style_set, NULL),
+
   OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
 	         "maximum number of columns for M-q to fill text to",
@@ -347,4 +350,22 @@
   ZInitLocationInfo(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_mainwin_redisplay(owl_global_get_mainwin(&g));
+  return(ret);
 }
 
