Index: functions.c
===================================================================
--- functions.c	(revision 9a7b4f23cba7fc71c4e918b5cb8d5ca6789924e3)
+++ functions.c	(revision 9a7b4f23cba7fc71c4e918b5cb8d5ca6789924e3)
@@ -278,5 +278,5 @@
 }
 
-void owl_function_start_edit_win(const char *line, void (*callback)(owl_editwin *), void *data)
+void owl_function_start_edit_win(const char *line, void (*callback)(owl_editwin *), void *data, void (*cleanup)(void *))
 {
   owl_editwin *e;
@@ -284,8 +284,6 @@
 
   /* create and setup the editwin */
-  e = owl_global_get_typwin(&g);
-  owl_editwin_new_style(e, OWL_EDITWIN_STYLE_MULTILINE,
-			owl_global_get_msg_history(&g));
-  owl_editwin_clear(e);
+  e = owl_global_set_typwin_active(&g, OWL_EDITWIN_STYLE_MULTILINE,
+                                   owl_global_get_msg_history(&g));
   owl_editwin_set_dotsend(e);
   s = owl_sprintf("----> %s\n", line);
@@ -293,9 +291,6 @@
   owl_free(s);
 
-  /* make it active */
-  owl_global_set_typwin_active(&g);
-
-  owl_editwin_set_cbdata(owl_global_get_typwin(&g), data);
-  owl_global_set_buffercallback(&g, callback);
+  owl_editwin_set_cbdata(e, data, cleanup);
+  owl_editwin_set_callback(e, callback);
   owl_global_push_context(&g, OWL_CTX_EDITMULTI, e, "editmulti");
 }
@@ -313,6 +308,7 @@
 			 noun);
 
-  owl_function_start_edit_win(line, callback, NULL);
-  owl_global_set_buffercommand(&g, line);
+  owl_function_start_edit_win(line, callback,
+                              owl_strdup(line),
+                              owl_free);
 }
 
@@ -350,5 +346,6 @@
 
 void owl_callback_zwrite(owl_editwin *e) {
-  owl_function_zwrite(owl_editwin_get_command(e),
+  char *command = owl_editwin_get_cbdata(e);
+  owl_function_zwrite(command,
                       owl_editwin_get_text(e));
 }
@@ -459,5 +456,6 @@
 
 void owl_callback_aimwrite(owl_editwin *e) {
-  owl_function_aimwrite(owl_editwin_get_command(e),
+  char *command = owl_editwin_get_cbdata(e);
+  owl_function_aimwrite(command,
                         owl_editwin_get_text(e));
 }
@@ -894,5 +892,6 @@
 
 void owl_callback_aimlogin(owl_editwin *e) {
-  owl_function_aimlogin(owl_editwin_get_command(e),
+  char *user = owl_editwin_get_cbdata(e);
+  owl_function_aimlogin(user,
                         owl_editwin_get_text(e));
 }
@@ -1193,9 +1192,4 @@
 {
   owl_global_set_resize_pending(&g);
-}
-
-void owl_function_run_buffercommand(void)
-{
-  owl_editwin_do_callback(owl_global_get_typwin(&g));
 }
 
@@ -1917,12 +1911,21 @@
 }
 
+void owl_callback_command(owl_editwin *e)
+{
+  char *rv;
+  const char *line = owl_editwin_get_text(e);
+
+  rv = owl_function_command(line);
+   if (rv) {
+    owl_function_makemsg("%s", rv);
+    owl_free(rv);
+  }
+}
+
 void owl_function_start_command(const char *line)
 {
   owl_editwin *tw;
 
-  tw=owl_global_get_typwin(&g);
-  owl_global_set_typwin_active(&g);
-  owl_editwin_new_style(tw, OWL_EDITWIN_STYLE_ONELINE, 
-			owl_global_get_cmd_history(&g));
+  tw = owl_global_set_typwin_active(&g, OWL_EDITWIN_STYLE_ONELINE, owl_global_get_cmd_history(&g));
 
   owl_editwin_set_locktext(tw, "command: ");
@@ -1933,13 +1936,12 @@
 
   owl_global_push_context(&g, OWL_CTX_EDITLINE, tw, "editline");
-}
-
-void owl_function_start_question(const char *line)
+  owl_editwin_set_callback(tw, owl_callback_command);
+}
+
+owl_editwin *owl_function_start_question(const char *line)
 {
   owl_editwin *tw;
 
-  tw=owl_global_get_typwin(&g);
-  owl_global_set_typwin_active(&g);
-  owl_editwin_new_style(tw, OWL_EDITWIN_STYLE_ONELINE, owl_global_get_cmd_history(&g));
+  tw = owl_global_set_typwin_active(&g, OWL_EDITWIN_STYLE_ONELINE, owl_global_get_cmd_history(&g));
 
   owl_editwin_set_locktext(tw, line);
@@ -1948,14 +1950,14 @@
   owl_editwin_redisplay(tw);
 
-  owl_global_push_context(&g, OWL_CTX_EDITRESPONSE, tw, "editline");
-}
-
-void owl_function_start_password(const char *line)
+  owl_global_push_context(&g, OWL_CTX_EDITRESPONSE, tw, "editresponse");
+  return tw;
+}
+
+owl_editwin *owl_function_start_password(const char *line)
 {
   owl_editwin *tw;
 
-  tw=owl_global_get_typwin(&g);
-  owl_global_set_typwin_active(&g);
-  owl_editwin_new_style(tw, OWL_EDITWIN_STYLE_ONELINE, owl_global_get_cmd_history(&g));
+  tw = owl_global_set_typwin_active(&g, OWL_EDITWIN_STYLE_ONELINE, NULL);
+
   owl_editwin_set_echochar(tw, '*');
 
@@ -1966,4 +1968,5 @@
 
   owl_global_push_context(&g, OWL_CTX_EDITRESPONSE, tw, "editresponse");
+  return tw;
 }
 
@@ -2289,6 +2292,7 @@
  * instance is NULL then catch all messgaes in the class.  Returns the
  * name of the filter, which the caller must free.
+ * If 'related' is nonzero, encompass unclasses and .d classes as well.
  */
-char *owl_function_classinstfilt(const char *c, const char *i) 
+char *owl_function_classinstfilt(const char *c, const char *i, int related) 
 {
   owl_filter *f;
@@ -2297,14 +2301,21 @@
   char *class, *instance = NULL;
 
-  class = owl_util_baseclass(c);
-  if(i) {
-    instance = owl_util_baseclass(i);
+  if (related) {
+    class = owl_util_baseclass(c);
+    if (i) {
+      instance = owl_util_baseclass(i);
+    }
+  } else {
+    class = owl_strdup(c);
+    if (i) {
+      instance = owl_strdup(i);
+    }
   }
 
   /* name for the filter */
   if (!instance) {
-    filtname = owl_sprintf("class-%s", class);
-  } else {
-    filtname = owl_sprintf("class-%s-instance-%s", class, instance);
+    filtname = owl_sprintf("%sclass-%s", related ? "related-" : "", class);
+  } else {
+    filtname = owl_sprintf("%sclass-%s-instance-%s", related ? "related-" : "", class, instance);
   }
   /* downcase it */
@@ -2338,8 +2349,8 @@
   }
 
-  argbuff = owl_sprintf("class ^(un)*%s(\\.d)*$", tmpclass);
+  argbuff = owl_sprintf(related ? "class ^(un)*%s(\\.d)*$" : "class ^%s$", tmpclass);
   if (tmpinstance) {
     char *tmp = argbuff;
-    argbuff = owl_sprintf("%s and ( instance ^(un)*%s(\\.d)*$ )", tmp, tmpinstance);
+    argbuff = owl_sprintf(related ? "%s and ( instance ^(un)*%s(\\.d)*$ )" : "%s and instance ^%s$", tmp, tmpinstance);
     owl_free(tmp);
   }
@@ -2512,11 +2523,12 @@
  *    name to the AIM conversation with that user 
  */
-char *owl_function_smartfilter(int type)
+char *owl_function_smartfilter(int type, int invert_related)
 {
   const owl_view *v;
   const owl_message *m;
   char *zperson, *filtname=NULL;
-  const char *argv[1];
-  
+  const char *argv[2];
+  int related = owl_global_is_narrow_related(&g) ^ invert_related;
+
   v=owl_global_get_current_view(&g);
   m=owl_view_get_element(v, owl_global_get_curmsg(&g));
@@ -2562,5 +2574,5 @@
     /* narrow class MESSAGE, instance foo, recip * messages to class, inst */
     if (!strcasecmp(owl_message_get_class(m), "message")) {
-      filtname=owl_function_classinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
+      filtname=owl_function_classinstfilt(owl_message_get_class(m), owl_message_get_instance(m), related);
       return(filtname);
     }
@@ -2568,7 +2580,7 @@
     /* otherwise narrow to the class */
     if (type==0) {
-      filtname=owl_function_classinstfilt(owl_message_get_class(m), NULL);
+      filtname=owl_function_classinstfilt(owl_message_get_class(m), NULL, related);
     } else if (type==1) {
-      filtname=owl_function_classinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
+      filtname=owl_function_classinstfilt(owl_message_get_class(m), owl_message_get_instance(m), related);
     }
     return(filtname);
@@ -2576,8 +2588,7 @@
 
   /* pass it off to perl */
-  if(type) {
-    argv[0] = "-i";
-  };
-  return owl_perlconfig_message_call_method(m, "smartfilter", type ? 1 : 0, argv);
+  argv[0] = type ? "1" : "0";
+  argv[1] = related ? "1" : "0";
+  return owl_perlconfig_message_call_method(m, "smartfilter", 2, argv);
 }
 
@@ -3418,52 +3429,35 @@
   int i, j;
   owl_list anyone;
-  owl_message *m;
   owl_zbuddylist *zbl;
+  GList **zaldlist;
+  GList *zaldptr;
+  ZAsyncLocateData_t *zald;
   const char *user;
-  ZLocations_t location[200];
-  int numlocs, ret;
 
   if (!owl_global_is_havezephyr(&g)) return;
-
-  zbl=owl_global_get_zephyr_buddylist(&g);
+  owl_global_set_pseudologin_notify(&g, notify);
+  zbl = owl_global_get_zephyr_buddylist(&g);
+  zaldlist = owl_global_get_zaldlist(&g);
+
+  /* Clear the existing ZALDs first. */
+  zaldptr = g_list_first(*zaldlist);
+  while (zaldptr) {
+    ZFreeALD(zaldptr->data);
+    owl_free(zaldptr->data);
+    zaldptr = g_list_next(zaldptr);
+  }
+  g_list_free(*zaldlist);
+  *zaldlist = NULL;
 
   owl_list_create(&anyone);
-  ret=owl_zephyr_get_anyone_list(&anyone, NULL);
-
-  j=owl_list_get_size(&anyone);
-  for (i=0; i<j; i++) {
-    user=owl_list_get_element(&anyone, i);
-    ret=ZLocateUser(zstr(user), &numlocs, ZAUTH);
-    if (ret!=ZERR_NONE) {
-      owl_function_error("Error getting location for %s", user);
-      continue;
-    }
-    numlocs=200;
-    ret=ZGetLocations(location, &numlocs);
-    if (ret==0) {
-      if ((numlocs>0) && !owl_zbuddylist_contains_user(zbl, user)) {
-	/* Send a PSEUDO LOGIN! */
-	if (notify) {
-	  m=owl_malloc(sizeof(owl_message));
-	  owl_message_create_pseudo_zlogin(m, 0, user, location[0].host, location[0].time, location[0].tty);
-	  owl_global_messagequeue_addmsg(&g, m);
-	}
-	owl_zbuddylist_adduser(zbl, user);
-	owl_function_debugmsg("owl_function_zephyr_buddy_check: login for %s ", user);
-      } else if ((numlocs==0) && owl_zbuddylist_contains_user(zbl, user)) {
-	/* I don't think this ever happens (if there are 0 locations we should get an error from
-	 * ZGetLocations)
-	 */
-	owl_function_error("owl_function_zephyr_buddy_check: exceptional case logout for %s ",user);
-      }
-    } else if ((ret==ZERR_NOLOCATIONS) && owl_zbuddylist_contains_user(zbl, user)) {
-      /* Send a PSEUDO LOGOUT! */
-      if (notify) {
-	m=owl_malloc(sizeof(owl_message));
-	owl_message_create_pseudo_zlogin(m, 1, user, "", "", "");
-	owl_global_messagequeue_addmsg(&g, m);
-      }
-      owl_zbuddylist_deluser(zbl, user);
-      owl_function_debugmsg("owl_function_zephyr_buddy_check: logout for %s ",user);
+  owl_zephyr_get_anyone_list(&anyone, NULL);
+  j = owl_list_get_size(&anyone);
+  for (i = 0; i < j; i++) {
+    user = owl_list_get_element(&anyone, i);
+    zald = owl_malloc(sizeof(ZAsyncLocateData_t));
+    if (ZRequestLocations(zstr(user), zald, UNACKED, ZAUTH) == ZERR_NONE) {
+      *zaldlist = g_list_append(*zaldlist, zald);
+    } else {
+      owl_free(zald);
     }
   }
