Index: ChangeLog
===================================================================
--- ChangeLog	(revision 7131cf27e222a1d65458f3f645beeb4b09fd928a)
+++ ChangeLog	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -1,11 +1,19 @@
 $Id$
 
-1.2.4-pre
-	Temporary fix to bug where C-SPACE would cause
-	     the key handler to lock up.
-	
 1.2.3
 	Added filters "ping", "auto" and "login" by default.
 	Added "body" as a valid field to match on in a filter.
+	Temporary fix to bug where C-SPACE would cause the key handler to
+	     lock up.
+	Messages now have a direciton (in, out or none).  Filters can
+             this direction
+	Outbound messages are no longer type 'admin' but are of the
+	     appropriate message type (i.e. 'zephyr') and are direction
+	     'out'.
+	Smartnarrow now works on outgoing messages
+	'info' updated to show more information for admin and outgoing
+	     messages
+	Renamed pretty_sender to short_zuser and renamed long_sender to
+             long_zuser
 	
 1.2.2
Index: filter.c
===================================================================
--- filter.c	(revision 75be7c0ff2043653b011d1c8cd4212a47f635482)
+++ filter.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -59,5 +59,6 @@
 	  !strcasecmp(argv[i], "opcode") ||
 	  !strcasecmp(argv[i], "realm") ||
-	  !strcasecmp(argv[i], "type")) {
+	  !strcasecmp(argv[i], "type") ||
+	  !strcasecmp(argv[i], "direction")) {
 	owl_filterelement_create_re(fe, argv[i], argv[i+1]);
 	i++;
@@ -142,8 +143,18 @@
       match=owl_message_get_realm(m);
     } else if (!strcasecmp(field, "type")) {
-      if (owl_message_is_zephyr(m)) {
+      if (owl_message_is_type_zephyr(m)) {
 	match="zephyr";
-      } else if (owl_message_is_admin(m)) {
+      } else if (owl_message_is_type_admin(m)) {
 	match="admin";
+      } else {
+	match="";
+      }
+    } else if (!strcasecmp(field, "direction")) {
+      if (owl_message_is_direction_out(m)) {
+	match="out";
+      } else if (owl_message_is_direction_in(m)) {
+	match="in";
+      } else if (owl_message_is_direction_none(m)) {
+	match="none";
       } else {
 	match="";
Index: fmtext.c
===================================================================
--- fmtext.c	(revision 1fd0b25bc362ef6deee5d05e4558ce154f8c6f5c)
+++ fmtext.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -494,4 +494,11 @@
 }
 
+void owl_fmtext_set_char(owl_fmtext *f, int index, int ch) {
+  /* set the charater at 'index' to be 'char'.  If index is out of
+   * bounds don't do anything */
+  if ((index < 0) || (index > f->textlen-1)) return;
+  f->textbuff[index]=ch;
+}
+
 void owl_fmtext_free(owl_fmtext *f) {
   if (f->textbuff) owl_free(f->textbuff);
Index: functions.c
===================================================================
--- functions.c	(revision 135445616d58ca580c37628f9d041ed32e8e1d0a)
+++ functions.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -22,5 +22,5 @@
 void owl_function_command_norv(char *cmdbuff) {
   char *rv;
-  rv = owl_function_command(cmdbuff);
+  rv=owl_function_command(cmdbuff);
   if (rv) owl_free(rv);
 }
@@ -80,12 +80,40 @@
 }
 
-void owl_function_adminmsg_outgoing(char *header, char *body, char *zwriteline) {
+void owl_function_make_outgoing_zephyr(char *header, char *body, char *zwriteline) {
   owl_message *m;
   int followlast;
+  owl_zwrite z;
+  char *tobuff, *recip;
   
   followlast=owl_global_should_followlast(&g);
+
+  /* create a zwrite for the purpose of filling in other message fields */
+  owl_zwrite_create_from_line(&z, zwriteline);
+
+  /* in 'tobuff' place the "Message sent to foo" string.
+   * Right now this only works for one recipient */
+  tobuff=owl_malloc(strlen(owl_zwrite_get_recip_n(&z, 0))+100);
+  sprintf(tobuff, "Zephyr sent to %s", owl_zwrite_get_recip_n(&z, 0));
+
+  /* create the message */
   m=owl_malloc(sizeof(owl_message));
-  owl_message_create_admin(m, header, body);
-  owl_message_set_admin_outgoing(m, zwriteline);
+  owl_message_create(m,  tobuff, body);
+  owl_message_set_direction_out(m);
+  owl_message_set_type_zephyr(m);
+
+  /* set zwriteline */
+  owl_message_set_zwriteline(m, zwriteline);
+
+  owl_message_set_class(m, owl_zwrite_get_class(&z));
+  owl_message_set_instance(m, owl_zwrite_get_instance(&z));
+  owl_message_set_opcode(m, owl_zwrite_get_opcode(&z));
+  owl_message_set_realm(m, owl_zwrite_get_realm(&z));
+  owl_message_set_sender(m, ZGetSender());
+  /* this only gets the first recipient for now, must fix */
+  recip=long_zuser(owl_zwrite_get_recip_n(&z, 0));
+  owl_message_set_recipient(m, recip);
+  owl_free(recip);
+
+  /* add it to the global list */
   owl_messagelist_append_element(owl_global_get_msglist(&g), m);
   owl_view_consider_message(owl_global_get_current_view(&g), m);
@@ -100,4 +128,5 @@
   wnoutrefresh(owl_global_get_curs_recwin(&g));
   owl_global_set_needrefresh(&g);
+  owl_free(tobuff);
 }
 
@@ -158,5 +187,5 @@
     owl_zwrite_get_recipstr(&z, buff);
     tmpbuff = owl_sprintf("Message sent to %s", buff);
-    owl_function_adminmsg_outgoing(tmpbuff, owl_editwin_get_text(owl_global_get_typwin(&g)), line);
+    owl_function_make_outgoing_zephyr(tmpbuff, owl_editwin_get_text(owl_global_get_typwin(&g)), line);
     owl_free(tmpbuff);
   }
@@ -289,5 +318,4 @@
   owl_function_nextmsg_full(NULL, 1, 1);
 }
-
 
 void owl_function_prevmsg_notdeleted() {
@@ -1059,5 +1087,5 @@
   owl_message *m;
   ZNotice_t *n;
-  char buff[2048], tmpbuff[1024];
+  char buff[5000], tmpbuff[1024];
   char *ptr;
   int i, j, fields, len;
@@ -1065,7 +1093,5 @@
 
   v=owl_global_get_current_view(&g);
-  
   m=owl_view_get_element(v, owl_global_get_curmsg(&g));
-
   if (!m || owl_view_get_size(v)==0) {
     owl_function_makemsg("No message selected\n");
@@ -1073,19 +1099,49 @@
   }
 
-  if (!owl_message_is_zephyr(m)) {
-    sprintf(buff,   "Owl Message Id: %i\n", owl_message_get_id(m));
-    sprintf(buff, "%sTime          : %s\n", buff, owl_message_get_timestr(m));
+  sprintf(buff,     "Msg Id    : %i\n", owl_message_get_id(m));
+  if (owl_message_is_type_zephyr(m)) {
+    sprintf(buff, "%sType      : zephyr\n", buff);
+  } else if (owl_message_is_type_admin(m)) {
+    sprintf(buff, "%sType      : admin\n", buff);
+  } else if (owl_message_is_type_generic(m)) {
+    sprintf(buff, "%sType      : generic\n", buff);
+  } else {
+    sprintf(buff, "%sType      : unknown\n", buff);
+  }
+  if (owl_message_is_direction_in(m)) {
+    sprintf(buff, "%sDirection : in\n", buff);
+  } else if (owl_message_is_direction_out(m)) {
+    sprintf(buff, "%sDirection : out\n", buff);
+  } else if (owl_message_is_direction_none(m)) {
+    sprintf(buff, "%sDirection : none\n", buff);
+  } else {
+    sprintf(buff, "%sDirection : unknown\n", buff);
+  }
+  sprintf(buff, "%sTime      : %s\n", buff, owl_message_get_timestr(m));
+
+  if (!owl_message_is_type_zephyr(m)) {
     owl_function_popless_text(buff);
     return;
   }
 
+
+  if (owl_message_is_direction_out(m)) {
+    sprintf(buff, "%sClass     : %s\n", buff, owl_message_get_class(m));
+    sprintf(buff, "%sInstance  : %s\n", buff, owl_message_get_instance(m));
+    sprintf(buff, "%sSender    : %s\n", buff, owl_message_get_sender(m));
+    sprintf(buff, "%sRecip     : %s\n", buff, owl_message_get_recipient(m));
+    sprintf(buff, "%sOpcode    : %s\n", buff, owl_message_get_opcode(m));
+    
+    owl_function_popless_text(buff);
+    return;
+  }
+
   n=owl_message_get_notice(m);
 
-  sprintf(buff,   "Owl Msg ID: %i\n", owl_message_get_id(m));
-  sprintf(buff, "%sClass     : %s\n", buff, n->z_class);
-  sprintf(buff, "%sInstance  : %s\n", buff, n->z_class_inst);
-  sprintf(buff, "%sSender    : %s\n", buff, n->z_sender);
-  sprintf(buff, "%sRecip     : %s\n", buff, n->z_recipient);
-  sprintf(buff, "%sOpcode    : %s\n", buff, n->z_opcode);
+  sprintf(buff, "%sClass     : %s\n", buff, owl_message_get_class(m));
+  sprintf(buff, "%sInstance  : %s\n", buff, owl_message_get_instance(m));
+  sprintf(buff, "%sSender    : %s\n", buff, owl_message_get_sender(m));
+  sprintf(buff, "%sRecip     : %s\n", buff, owl_message_get_recipient(m));
+  sprintf(buff, "%sOpcode    : %s\n", buff, owl_message_get_opcode(m));
   strcat(buff,    "Kind      : ");
   if (n->z_kind==UNSAFE) {
@@ -1505,12 +1561,10 @@
       }
     }
-    
-    if (owl_message_is_admin(m)) {
-      if (owl_message_get_admintype(m)==OWL_MESSAGE_ADMINTYPE_OUTGOING) {
-	owl_function_zwrite_setup(owl_message_get_zwriteline(m));
-	owl_global_set_buffercommand(&g, owl_message_get_zwriteline(m));
-      } else {
-	owl_function_makemsg("You cannot reply to this admin message");
-      }
+
+    if (owl_message_is_direction_out(m)) {
+      owl_function_zwrite_setup(owl_message_get_zwriteline(m));
+      owl_global_set_buffercommand(&g, owl_message_get_zwriteline(m));
+    } else if (owl_message_is_type_admin(m)) {
+      owl_function_makemsg("You cannot reply to this admin message");
     } else {
       if (owl_message_is_login(m)) {
@@ -1548,5 +1602,5 @@
       if (*to != '\0') {
 	char *tmp, *oldtmp;
-	tmp=pretty_sender(to);
+	tmp=short_zuser(to);
 	if (cc) {
 	  tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
@@ -1555,5 +1609,5 @@
 	  owl_free(oldbuff);
 	} else {
-	  tmp=pretty_sender(to);
+	  tmp=short_zuser(to);
 	  buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
 	  owl_free(oldbuff);
@@ -1902,6 +1956,6 @@
 
   /* stick the local realm on if it's not there */
-  longuser=long_sender(user);
-  shortuser=pretty_sender(user);
+  longuser=long_zuser(user);
+  shortuser=short_zuser(user);
 
   /* name for the filter */
@@ -1917,8 +1971,8 @@
   f=owl_malloc(sizeof(owl_filter));
 
-  argbuff=owl_malloc(strlen(longuser)+200);
-  sprintf(argbuff, "( ( class ^message$ ) and ( instance ^personal$ ) and ( sender ^%s$ ) )", longuser);
-  sprintf(argbuff, "%s or ( ( type ^admin$ ) and ( recipient %s ) )", argbuff, shortuser);
-  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) )", argbuff, longuser);
+  argbuff=owl_malloc(strlen(longuser)+1000);
+  sprintf(argbuff, "( type ^zephyr$ and ( class ^message$ and instance ^personal$ and ");
+  sprintf(argbuff, "%s ( ( direction ^in$ and sender ^%s$ ) or ( direction ^out$ and recipient ^%s$ ) ) )", argbuff, longuser, longuser);
+  sprintf(argbuff, "%s or ( ( class ^login$ ) and ( sender ^%s$ ) ) )", argbuff, longuser);
 
   owl_filter_init_fromstring(f, filtname, argbuff);
@@ -1998,5 +2052,5 @@
   owl_view *v;
   owl_message *m;
-  char *sender, *filtname=NULL;
+  char *zperson, *filtname=NULL;
   
   v=owl_global_get_current_view(&g);
@@ -2005,21 +2059,25 @@
   if (!m || owl_view_get_size(v)==0) {
     owl_function_makemsg("No message selected\n");
-    return NULL;
+    return(NULL);
   }
 
   /* very simple handling of admin messages for now */
-  if (owl_message_is_admin(m)) {
-    return owl_function_fasttypefilt("admin");
-  }
-
-  /* narrow personal and login messages to the sender */
+  if (owl_message_is_type_admin(m)) {
+    return(owl_function_fasttypefilt("admin"));
+  }
+
+  /* narrow personal and login messages to the sender or recip as appropriate */
   if (owl_message_is_personal(m) || owl_message_is_login(m)) {
-    if (owl_message_is_zephyr(m)) {
-      sender=pretty_sender(owl_message_get_sender(m));
-      filtname = owl_function_fastuserfilt(sender);
-      owl_free(sender);
-      return filtname;
-    }
-    return NULL;
+    if (owl_message_is_type_zephyr(m)) {
+      if (owl_message_is_direction_in(m)) {
+	zperson=short_zuser(owl_message_get_sender(m));
+      } else {
+	zperson=short_zuser(owl_message_get_recipient(m));
+      }
+      filtname=owl_function_fastuserfilt(zperson);
+      owl_free(zperson);
+      return(filtname);
+    }
+    return(NULL);
   }
 
@@ -2027,15 +2085,15 @@
   if (!strcasecmp(owl_message_get_class(m), "message") &&
       !owl_message_is_personal(m)) {
-    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
-    return filtname;
+    filtname=owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
+    return(filtname);
   }
 
   /* otherwise narrow to the class */
   if (type==0) {
-    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), NULL);
+    filtname=owl_function_fastclassinstfilt(owl_message_get_class(m), NULL);
   } else if (type==1) {
-    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
-  }
-  return filtname;
+    filtname=owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
+  }
+  return(filtname);
 }
 
@@ -2056,7 +2114,7 @@
 
   /* for now we skip admin messages. */
-  if (owl_message_is_admin(m)
+  if (owl_message_is_type_admin(m)
       || owl_message_is_login(m)
-      || !owl_message_is_zephyr(m)) {
+      || !owl_message_is_type_zephyr(m)) {
     owl_function_makemsg("smartzpunt doesn't support this message type.");
     return;
@@ -2241,5 +2299,4 @@
 }
 
-
 void owl_function_help_for_command(char *cmdname) {
   owl_fmtext fm;
Index: logging.c
===================================================================
--- logging.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
+++ logging.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -131,5 +131,5 @@
   }
 
-  tmp=pretty_sender(owl_message_get_sender(m));
+  tmp=short_zuser(owl_message_get_sender(m));
   
   fprintf(file, "Class: %s Instance: %s", owl_message_get_class(m), owl_message_get_instance(m));
Index: message.c
===================================================================
--- message.c	(revision 1fd0b25bc362ef6deee5d05e4558ce154f8c6f5c)
+++ message.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -13,13 +13,12 @@
 static const char fileIdent[] = "$Id$";
 
-void owl_message_create_admin(owl_message *m, char *header, char *text) {
-  char *indent;
+void owl_message_init_raw(owl_message *m) {
   time_t t;
 
   m->id=owl_global_get_nextmsgid(&g);
-  m->type=OWL_MESSAGE_TYPE_ADMIN;
-  m->admintype=OWL_MESSAGE_ADMINTYPE_GENERIC;
+  m->type=OWL_MESSAGE_TYPE_GENERIC;
+  owl_message_set_direction_none(m);
   m->delete=0;
-  m->sender=owl_strdup("-owl");
+  m->sender=owl_strdup("");
   m->class=owl_strdup("");
   m->inst=owl_strdup("");
@@ -34,4 +33,295 @@
   m->time=owl_strdup(ctime(&t));
   m->time[strlen(m->time)-1]='\0';
+}
+
+
+owl_fmtext *owl_message_get_fmtext(owl_message *m) {
+  return(&(m->fmtext));
+}
+
+void owl_message_set_class(owl_message *m, char *class) {
+  if (m->class) owl_free(m->class);
+  m->class=owl_strdup(class);
+}
+
+char *owl_message_get_class(owl_message *m) {
+  return(m->class);
+}
+
+void owl_message_set_instance(owl_message *m, char *inst) {
+  if (m->inst) owl_free(m->inst);
+  m->inst=owl_strdup(inst);
+}
+
+char *owl_message_get_instance(owl_message *m) {
+  return(m->inst);
+}
+
+void owl_message_set_sender(owl_message *m, char *sender) {
+  if (m->sender) owl_free(m->sender);
+  m->sender=owl_strdup(sender);
+}
+
+char *owl_message_get_sender(owl_message *m) {
+  return(m->sender);
+}
+
+void owl_message_set_recipient(owl_message *m, char *recip) {
+  if (m->recip) owl_free(m->recip);
+  m->recip=owl_strdup(recip);
+}
+
+char *owl_message_get_recipient(owl_message *m) {
+  /* this is stupid for outgoing messages, we need to fix it. */
+     
+  if (m->type==OWL_MESSAGE_TYPE_ZEPHYR) {
+    return(m->recip);
+  } else if (owl_message_is_direction_out(m)) {
+    return(m->zwriteline);
+  } else {
+    return(m->recip);
+  }
+}
+
+void owl_message_set_realm(owl_message *m, char *realm) {
+  if (m->realm) owl_free(m->realm);
+  m->realm=owl_strdup(realm);
+}
+
+char *owl_message_get_realm(owl_message *m) {
+  return(m->realm);
+}
+
+void owl_message_set_opcode(owl_message *m, char *opcode) {
+  if (m->opcode) free(m->opcode);
+  m->opcode=owl_strdup(opcode);
+}
+
+char *owl_message_get_opcode(owl_message *m) {
+  return(m->opcode);
+}
+
+char *owl_message_get_timestr(owl_message *m) {
+  return(m->time);
+}
+
+void owl_message_set_type_admin(owl_message *m) {
+  m->type=OWL_MESSAGE_TYPE_ADMIN;
+}
+
+void owl_message_set_type_zephyr(owl_message *m) {
+  m->type=OWL_MESSAGE_TYPE_ZEPHYR;
+}
+						
+int owl_message_is_type_admin(owl_message *m) {
+  if (m->type==OWL_MESSAGE_TYPE_ADMIN) return(1);
+  return(0);
+}
+
+int owl_message_is_type_zephyr(owl_message *m) {
+  if (m->type==OWL_MESSAGE_TYPE_ZEPHYR) return(1);
+  return(0);
+}
+
+int owl_message_is_type_generic(owl_message *m) {
+  if (m->type==OWL_MESSAGE_TYPE_GENERIC) return(1);
+  return(0);
+}
+
+char *owl_message_get_text(owl_message *m) {
+  return(owl_fmtext_get_text(&(m->fmtext)));
+}
+
+char *owl_message_get_body(owl_message *m) {
+  return(m->body);
+}
+
+void owl_message_set_direction_in(owl_message *m) {
+  m->direction=OWL_MESSAGE_DIRECTION_IN;
+}
+
+void owl_message_set_direction_out(owl_message *m) {
+  m->direction=OWL_MESSAGE_DIRECTION_OUT;
+}
+
+void owl_message_set_direction_none(owl_message *m) {
+  m->direction=OWL_MESSAGE_DIRECTION_NONE;
+}
+
+int owl_message_is_direction_in(owl_message *m) {
+  if (m->direction==OWL_MESSAGE_DIRECTION_IN) return(1);
+  return(0);
+}
+
+int owl_message_is_direction_out(owl_message *m) {
+  if (m->direction==OWL_MESSAGE_DIRECTION_OUT) return(1);
+  return(0);
+}
+
+int owl_message_is_direction_none(owl_message *m) {
+  if (m->direction==OWL_MESSAGE_DIRECTION_NONE) return(1);
+  return(0);
+}
+
+int owl_message_get_numlines(owl_message *m) {
+  if (m == NULL) return(0);
+  return(owl_fmtext_num_lines(&(m->fmtext)));
+}
+
+void owl_message_mark_delete(owl_message *m) {
+  if (m == NULL) return;
+  m->delete=1;
+}
+
+void owl_message_unmark_delete(owl_message *m) {
+  if (m == NULL) return;
+  m->delete=0;
+}
+
+char *owl_message_get_zwriteline(owl_message *m) {
+  return(m->zwriteline);
+}
+
+void owl_message_set_zwriteline(owl_message *m, char *line) {
+  m->zwriteline=strdup(line);
+}
+
+int owl_message_is_delete(owl_message *m) {
+  if (m == NULL) return(0);
+  if (m->delete==1) return(1);
+  return(0);
+}
+
+ZNotice_t *owl_message_get_notice(owl_message *m) {
+  return(&(m->notice));
+}
+
+char *owl_message_get_hostname(owl_message *m) {
+  return(m->hostname);
+}
+
+
+void owl_message_curs_waddstr(owl_message *m, WINDOW *win, int aline, int bline, int acol, int bcol, int color) {
+  owl_fmtext a, b;
+
+  owl_fmtext_truncate_lines(&(m->fmtext), aline, bline-aline+1, &a);
+  owl_fmtext_truncate_cols(&a, acol, bcol, &b);
+  if (color!=OWL_COLOR_DEFAULT) {
+    owl_fmtext_colorize(&b, color);
+  }
+
+  if (owl_global_is_search_active(&g)) {
+    owl_fmtext_search_and_highlight(&b, owl_global_get_search_string(&g));
+  }
+      
+  owl_fmtext_curs_waddstr(&b, win);
+
+  owl_fmtext_free(&a);
+  owl_fmtext_free(&b);
+}
+
+int owl_message_is_personal(owl_message *m) {
+  if (strcasecmp(owl_message_get_class(m), "message")) return(0);
+  if (strcasecmp(owl_message_get_instance(m), "personal")) return(0);
+  if (!strcmp(owl_message_get_recipient(m), ZGetSender()) ||
+      !strcmp(owl_message_get_sender(m), ZGetSender())) {
+    return(1);
+  }
+  return(0);
+}
+
+int owl_message_is_private(owl_message *m) {
+  if (!strcmp(owl_message_get_recipient(m), ZGetSender())) return(1);
+  return(0);
+}
+
+int owl_message_is_mail(owl_message *m) {
+  if (!strcasecmp(owl_message_get_class(m), "mail") && owl_message_is_private(m)) {
+    return(1);
+  }
+  return(0);
+}
+
+int owl_message_is_ping(owl_message *m) {
+  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return(1);
+  return(0);
+}
+
+int owl_message_is_login(owl_message *m) {
+  if (!strcasecmp(owl_message_get_class(m), "login")) return(1);
+  return(0);
+  /* is this good enough? */
+}
+
+int owl_message_is_burningears(owl_message *m) {
+  /* we should add a global to cache the short zsender */
+  char sender[LINE], *ptr;
+
+  /* if the message is from us or to us, it doesn't count */
+  if (!strcasecmp(ZGetSender(), owl_message_get_sender(m))) return(0);
+  if (!strcasecmp(ZGetSender(), owl_message_get_recipient(m))) return(0);
+
+  strcpy(sender, ZGetSender());
+  ptr=strchr(sender, '@');
+  if (ptr) *ptr='\0';
+
+  if (stristr(owl_message_get_body(m), sender)) {
+    return(1);
+  }
+  return(0);
+}
+
+/* caller must free return value. */
+char *owl_message_get_cc(owl_message *m) {
+  char *cur, *out, *end;
+
+  cur = owl_message_get_body(m);
+  while (*cur && *cur==' ') cur++;
+  if (strncasecmp(cur, "cc:", 2)) return(NULL);
+  cur+=3;
+  while (*cur && *cur==' ') cur++;
+  out = owl_strdup(cur);
+  end = strchr(out, '\n');
+  if (end) end[0] = '\0';
+  return(out);
+}
+
+int owl_message_get_id(owl_message *m) {
+  return(m->id);
+}
+					
+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 */
+
+  return (owl_fmtext_search(&(m->fmtext), string));
+}
+
+void owl_message_create(owl_message *m, char *header, char *text) {
+  char *indent;
+
+  owl_message_init_raw(m);
+
+  m->body=owl_strdup(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);
+}
+
+void owl_message_create_admin(owl_message *m, char *header, char *text) {
+  char *indent;
+
+  owl_message_init_raw(m);
+  owl_message_set_type_admin(m);
 
   m->body=owl_strdup(text);
@@ -60,5 +350,6 @@
 
   m->id=owl_global_get_nextmsgid(&g);
-  m->type=OWL_MESSAGE_TYPE_ZEPHYR;
+  owl_message_set_type_zephyr(m);
+  owl_message_set_direction_in(m);
   
   /* first save the full notice */
@@ -194,5 +485,5 @@
     }
     owl_fmtext_append_normal(&(m->fmtext), " for ");
-    ptr=pretty_sender(n->z_class_inst);
+    ptr=short_zuser(n->z_class_inst);
     owl_fmtext_append_bold(&(m->fmtext), ptr);
     owl_free(ptr);
@@ -297,5 +588,5 @@
     }
     owl_fmtext_append_normal(&(m->fmtext), " for ");
-    ptr=pretty_sender(n->z_class_inst);
+    ptr=short_zuser(n->z_class_inst);
     owl_fmtext_append_bold(&(m->fmtext), ptr);
     owl_free(ptr);
@@ -376,59 +667,6 @@
 
 
-int owl_message_get_numlines(owl_message *m) {
-  if (m == NULL) return(0);
-  return(owl_fmtext_num_lines(&(m->fmtext)));
-}
-
-
-void owl_message_mark_delete(owl_message *m) {
-  if (m == NULL) return;
-  m->delete=1;
-  /* _owl_message_make_text_from_notice(m); */
-}
-
-
-void owl_message_unmark_delete(owl_message *m) {
-  if (m == NULL) return;
-  m->delete=0;
-}
-
-
-int owl_message_set_admintype(owl_message *m, int admintype) {
-  if (m->type != OWL_MESSAGE_TYPE_ADMIN) return(-1);
-  m->admintype=admintype;
-  return(0);
-}
-
-
-int owl_message_get_admintype(owl_message *m) {
-  return(m->admintype);
-}
-
-void owl_message_set_admin_outgoing(owl_message *m, char *zwriteline) {
-  owl_message_set_admintype(m, OWL_MESSAGE_ADMINTYPE_OUTGOING);
-  if (m->zwriteline) {
-    owl_free(m->zwriteline);
-    m->zwriteline=owl_strdup(zwriteline);
-  }
-}
-
-char *owl_message_get_zwriteline(owl_message *m) {
-  return(m->zwriteline);
-}
-
-int owl_message_is_delete(owl_message *m) {
-  if (m == NULL) return(0);
-  if (m->delete==1) return(1);
-  return(0);
-}
-
-ZNotice_t *owl_message_get_notice(owl_message *m) {
-  return(&(m->notice));
-}
-
-
 void owl_message_free(owl_message *m) {
-  if (owl_message_is_zephyr(m)) {
+  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
     ZFreeNotice(&(m->notice));
   }
@@ -446,193 +684,2 @@
 }
 
-
-char *owl_message_get_hostname(owl_message *m) {
-  return(m->hostname);
-}
-
-
-void owl_message_curs_waddstr(owl_message *m, WINDOW *win, int aline, int bline, int acol, int bcol, int color) {
-  owl_fmtext a, b;
-
-  owl_fmtext_truncate_lines(&(m->fmtext), aline, bline-aline+1, &a);
-  owl_fmtext_truncate_cols(&a, acol, bcol, &b);
-  if (color!=OWL_COLOR_DEFAULT) {
-    owl_fmtext_colorize(&b, color);
-  }
-
-  if (owl_global_is_search_active(&g)) {
-    owl_fmtext_search_and_highlight(&b, owl_global_get_search_string(&g));
-  }
-      
-  owl_fmtext_curs_waddstr(&b, win);
-
-  owl_fmtext_free(&a);
-  owl_fmtext_free(&b);
-}
-
-owl_fmtext *owl_message_get_fmtext(owl_message *m) {
-  return(&(m->fmtext));
-}
-
-void owl_message_set_class(owl_message *m, char *class) {
-  if (m->class) owl_free(m->class);
-  m->class=owl_strdup(class);
-}
-
-
-char *owl_message_get_class(owl_message *m) {
-  return(m->class);
-}
-
-void owl_message_set_instance(owl_message *m, char *inst) {
-  if (m->inst) owl_free(m->inst);
-  m->inst=owl_strdup(inst);
-}
-
-char *owl_message_get_instance(owl_message *m) {
-  return(m->inst);
-}
-
-void owl_message_set_sender(owl_message *m, char *sender) {
-  if (m->sender) owl_free(m->sender);
-  m->sender=owl_strdup(sender);
-}
-
-char *owl_message_get_sender(owl_message *m) {
-  return(m->sender);
-}
-
-void owl_message_set_recipient(owl_message *m, char *recip) {
-  if (m->recip) owl_free(m->recip);
-  m->recip=owl_strdup(recip);
-}
-
-char *owl_message_get_recipient(owl_message *m) {
-  /* this is very, very stupid for outgoing messages, we need to
-     fix that. */
-     
-  if (m->type==OWL_MESSAGE_TYPE_ZEPHYR) {
-    return(m->recip);
-  } else if (m->type==OWL_MESSAGE_TYPE_ADMIN &&
-	     m->admintype==OWL_MESSAGE_ADMINTYPE_OUTGOING) {
-    return(m->zwriteline);
-  } else {
-    return(m->recip);
-  }
-}
-
-void owl_message_set_realm(owl_message *m, char *realm) {
-  if (m->realm) owl_free(m->realm);
-  m->realm=owl_strdup(realm);
-}
-
-char *owl_message_get_realm(owl_message *m) {
-  return(m->realm);
-}
-
-void owl_message_set_opcode(owl_message *m, char *opcode) {
-  if (m->opcode) free(m->opcode);
-  m->opcode=owl_strdup(opcode);
-}
-
-char *owl_message_get_opcode(owl_message *m) {
-  return(m->opcode);
-}
-
-char *owl_message_get_timestr(owl_message *m) {
-  return(m->time);
-}
-
-int owl_message_is_admin(owl_message *m) {
-  if (m->type==OWL_MESSAGE_TYPE_ADMIN) return(1);
-  return(0);
-}
-
-int owl_message_is_zephyr(owl_message *m) {
-  if (m->type==OWL_MESSAGE_TYPE_ZEPHYR) return(1);
-  return(0);
-}
-
-char *owl_message_get_text(owl_message *m) {
-  return(owl_fmtext_get_text(&(m->fmtext)));
-}
-
-char *owl_message_get_body(owl_message *m) {
-  return(m->body);
-}
-
-int owl_message_is_personal(owl_message *m) {
-  if (!strcasecmp(owl_message_get_class(m), "message") &&
-      !strcasecmp(owl_message_get_instance(m), "personal") &&
-      !strcmp(owl_message_get_recipient(m), ZGetSender())) {
-    return(1);
-  }
-  return(0);
-}
-
-int owl_message_is_private(owl_message *m) {
-  if (!strcmp(owl_message_get_recipient(m), ZGetSender())) return(1);
-  return(0);
-}
-
-int owl_message_is_mail(owl_message *m) {
-  if (!strcasecmp(owl_message_get_class(m), "mail") && owl_message_is_private(m)) {
-    return(1);
-  }
-  return(0);
-}
-
-int owl_message_is_ping(owl_message *m) {
-  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return(1);
-  return(0);
-}
-
-int owl_message_is_login(owl_message *m) {
-  if (!strcasecmp(owl_message_get_class(m), "login")) return(1);
-  return(0);
-  /* is this good enough? */
-}
-
-int owl_message_is_burningears(owl_message *m) {
-  /* we should add a global to cache the short zsender */
-  char sender[LINE], *ptr;
-
-  /* if the message is from us or to us, it doesn't count */
-  if (!strcasecmp(ZGetSender(), owl_message_get_sender(m))) return(0);
-  if (!strcasecmp(ZGetSender(), owl_message_get_recipient(m))) return(0);
-
-  strcpy(sender, ZGetSender());
-  ptr=strchr(sender, '@');
-  if (ptr) *ptr='\0';
-
-  if (stristr(owl_message_get_body(m), sender)) {
-    return(1);
-  }
-  return(0);
-}
-
-/* caller must free return value. */
-char *owl_message_get_cc(owl_message *m) {
-  char *cur, *out, *end;
-
-  cur = owl_message_get_body(m);
-  while (*cur && *cur==' ') cur++;
-  if (strncasecmp(cur, "cc:", 2)) return(NULL);
-  cur+=3;
-  while (*cur && *cur==' ') cur++;
-  out = owl_strdup(cur);
-  end = strchr(out, '\n');
-  if (end) end[0] = '\0';
-  return(out);
-}
-
-int owl_message_get_id(owl_message *m) {
-  return(m->id);
-}
-					
-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 */
-
-  return (owl_fmtext_search(&(m->fmtext), string));
-}
Index: owl.c
===================================================================
--- owl.c	(revision 0236842b1ea4c3864408a3f3c39b042e590322e1)
+++ owl.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -34,4 +34,6 @@
   char **argvsave;
   owl_filter *f;
+  time_t nexttime;
+  int nexttimediff;
 
   argcsave=argc;
@@ -217,4 +219,7 @@
   owl_context_set_interactive(owl_global_get_context(&g));
 
+  nexttimediff=20;
+  nexttime=time(NULL);
+
   /* main loop */
   while (1) {
@@ -230,4 +235,17 @@
 
     followlast=owl_global_should_followlast(&g);
+
+    /* little hack */
+    if (0 && owl_global_get_runtime(&g)<300) {
+      if (time(NULL)>nexttime) {
+	if (nexttimediff==1) {
+	  nexttimediff=20;
+	} else {
+	  nexttimediff=1;
+	}
+	nexttime+=nexttimediff;
+	owl_hack_animate();
+      }
+    }
 
     /* grab incoming zephyrs */
Index: owl.h
===================================================================
--- owl.h	(revision 60ffe0451942f325240f19bf245ba511a6ba5ca7)
+++ owl.h	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -36,10 +36,11 @@
 #define OWL_EDITWIN_STYLE_ONELINE   1
 
-#define OWL_MESSAGE_TYPE_ADMIN  0
-#define OWL_MESSAGE_TYPE_ZEPHYR 1
-
-#define OWL_MESSAGE_ADMINTYPE_GENERIC  0
-#define OWL_MESSAGE_ADMINTYPE_OUTGOING 1
-#define OWL_MESSAGE_ADMINTYPE_NOTADMIN 2
+#define OWL_MESSAGE_TYPE_ADMIN      0
+#define OWL_MESSAGE_TYPE_GENERIC    1
+#define OWL_MESSAGE_TYPE_ZEPHYR     2
+
+#define OWL_MESSAGE_DIRECTION_NONE  0
+#define OWL_MESSAGE_DIRECTION_IN    1
+#define OWL_MESSAGE_DIRECTION_OUT   2
 
 #define OWL_DIRECTION_NONE      0
@@ -53,5 +54,4 @@
 #define OWL_SCROLLMODE_PAGED    4
 #define OWL_SCROLLMODE_PAGEDCENTER 5
-
 
 #define OWL_TAB               3  /* This *HAS* to be the size of TABSTR below */
@@ -96,12 +96,12 @@
 #define OWL_FILTER_MAX_DEPTH    300
 
-#define OWL_KEYMAP_MAXSTACK 20
-
-#define OWL_KEYBINDING_COMMAND   1 /* command string */
-#define OWL_KEYBINDING_FUNCTION  2 /* function taking no args */
-
-#define OWL_DEFAULT_ZAWAYMSG "I'm sorry, but I am currently away from the terminal and am\nnot able to receive your message.\n"
-
-#define OWL_INCLUDE_REG_TESTS  1  /* whether to build in regression tests */
+#define OWL_KEYMAP_MAXSTACK     20
+
+#define OWL_KEYBINDING_COMMAND  1   /* command string */
+#define OWL_KEYBINDING_FUNCTION 2   /* function taking no args */
+
+#define OWL_DEFAULT_ZAWAYMSG    "I'm sorry, but I am currently away from the terminal and am\nnot able to receive your message.\n"
+
+#define OWL_INCLUDE_REG_TESTS   1  /* whether to build in regression tests */
 
 #define OWL_CMD_ALIAS_SUMMARY_PREFIX "command alias to: "
@@ -227,5 +227,5 @@
   int id;
   int type;
-  int admintype;
+  int direction;
   ZNotice_t notice;
   owl_fmtext fmtext;
Index: readconfig.c
===================================================================
--- readconfig.c	(revision 67103d47934f4d977ff90e3f9e94bd373bfddca1)
+++ readconfig.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -159,7 +159,7 @@
 
   /* set owl::type */
-  if (owl_message_is_zephyr(m)) {
+  if (owl_message_is_type_zephyr(m)) {
     sv_setpv(perl_get_sv("owl::type", TRUE), "zephyr");
-  } else if (owl_message_is_admin(m)) {
+  } else if (owl_message_is_type_admin(m)) {
     sv_setpv(perl_get_sv("owl::type", TRUE), "admin");
   } else {
Index: util.c
===================================================================
--- util.c	(revision 1fd0b25bc362ef6deee5d05e4558ce154f8c6f5c)
+++ util.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -392,5 +392,5 @@
 }
 
-char *pretty_sender(char *in) {
+char *short_zuser(char *in) {
   char *out, *ptr;
   
@@ -406,5 +406,5 @@
 }
 
-char *long_sender(char *in) {
+char *long_zuser(char *in) {
   char *ptr;
 
@@ -494,4 +494,42 @@
 }
 
+void owl_hack_animate() {
+  owl_messagelist *ml;
+  owl_message *m;
+  owl_fmtext *fm;
+  char *text, *ptr;
+  int place;
+
+  /* grab the first message and make sure its id is 0 */
+  ml=owl_global_get_msglist(&g);
+  m=owl_messagelist_get_element(ml, 0);
+  if (!m) return;
+  if (owl_message_get_id(m)!=0) return;
+
+  fm=owl_message_get_fmtext(m);
+  text=owl_fmtext_get_text(fm);
+
+  ptr=strstr(text, "OvO");
+  if (ptr) {
+    place=ptr-text;
+    owl_fmtext_set_char(fm, place, '-');
+    owl_fmtext_set_char(fm, place+2, '-');
+
+    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
+    owl_global_set_needrefresh(&g);
+    return;
+  }
+
+  ptr=strstr(text, "-v-");
+  if (ptr) {
+    place=ptr-text;
+    owl_fmtext_set_char(fm, place, 'O');
+    owl_fmtext_set_char(fm, place+2, 'O');
+
+    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
+    owl_global_set_needrefresh(&g);
+    return;
+  }
+}
 
 /**************************************************************************/
Index: zephyr.c
===================================================================
--- zephyr.c	(revision 1c6c4d32e1e8e1d158e1586d924d0c440edc8a8b)
+++ zephyr.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -359,5 +359,5 @@
     } else if (!strcasecmp(retnotice->z_class, "message") &&
 	       !strcasecmp(retnotice->z_class_inst, "personal")) {
-      tmp=pretty_sender(retnotice->z_recipient);
+      tmp=short_zuser(retnotice->z_recipient);
       owl_function_makemsg("Message sent to %s.", tmp);
       free(tmp);
@@ -370,5 +370,5 @@
 	      retnotice->z_class, retnotice->z_class_inst);
     } else {
-      tmp = pretty_sender(retnotice->z_recipient);
+      tmp = short_zuser(retnotice->z_recipient);
       owl_function_makemsg("%s: Not logged in or subscribing to messages.", 
 			   tmp);
@@ -446,5 +446,5 @@
   for (;numlocs;numlocs--) {
     ZGetLocations(&locations,&one);
-    myuser=pretty_sender(user);
+    myuser=short_zuser(user);
     sprintf(out, "%s%s: %s\t%s\t%s\n", out, myuser, locations.host, locations.tty, locations.time);
     owl_free(myuser);
Index: zwrite.c
===================================================================
--- zwrite.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
+++ zwrite.c	(revision 4b464a43720ec7191ae97a55c10c3e66721ed93f)
@@ -182,4 +182,8 @@
 }
 
+char *owl_zwrite_get_opcode(owl_zwrite *z) {
+  return(z->opcode);
+}
+
 char *owl_zwrite_get_realm(owl_zwrite *z) {
   return(z->realm);
@@ -219,5 +223,4 @@
 }
   
-
 void owl_zwrite_free(owl_zwrite *z) {
   owl_list_free_all(&(z->recips), &owl_free);
