Index: ChangeLog
===================================================================
--- ChangeLog	(revision 855ebe73d6ff7c3de47cb9b5c8dbd6b35a6974b4)
+++ ChangeLog	(revision 7360fabdd3382148cdd83b2bcb1ea86f19f02c94)
@@ -19,4 +19,14 @@
 	Updated examples/owlconf.erik with the above.
 	Fixed the annoying pagedown sometimes-not-working bug.
+	Made owl_function_fast*filt return a string and not do the 
+	        narrowing, to make it more general.
+	Added a smartfilter command that creates a filter
+	        based on the current message and returns the name
+		of the filter.
+	Added --smart-filter and --smart-filter-instance options 
+	        to the next and prev commands.
+	Added M-C-n and M-C-p keybindings to "move to next message 
+	        matching current" and "move to previous message 
+		matching current"
 	
 1.2.0-pre-erikdevel-17
Index: commands.c
===================================================================
--- commands.c	(revision b9500884ebb34781929664a20fd81a6a0c8b867c)
+++ commands.c	(revision 7360fabdd3382148cdd83b2bcb1ea86f19f02c94)
@@ -195,8 +195,11 @@
   OWLCMD_ARGS("next", owl_command_next, OWL_CTX_INTERACTIVE,
 	      "move the pointer to the next message",
-	      "recv:next [ --filter <name> ] [ --skip-deleted ] [ --last-if-none ]",
+	      "recv:next [ --filter <name> ] [ --skip-deleted ] [ --last-if-none ]\n"
+	      "          [ --smart-filter | --smart-filter-instance ]",
 	      "Moves the pointer to the next message in the current view.\n"
 	      "If --filter is specified, will only consider messages in\n"
 	      "the filter <name>.\n"
+	      "If --smart-filter or --smart-filter-instance is specified,\n"
+	      "goes to the next message that is similar to the current message.\n"
 	      "If --skip-deleted is specified, deleted messages will\n"
 	      "be skipped.\n"
@@ -207,8 +210,11 @@
   OWLCMD_ARGS("prev", owl_command_prev, OWL_CTX_INTERACTIVE,
 	      "move the pointer to the previous message",
-	      "recv:prev [ --filter <name> ] [ --skip-deleted ] [ --first-if-none ]",
+	      "recv:prev [ --filter <name> ] [ --skip-deleted ] [ --first-if-none ]\n"
+	      "          [ --smart-filter | --smart-filter-instance ]",
 	      "Moves the pointer to the next message in the current view.\n"
 	      "If --filter is specified, will only consider messages in\n"
 	      "the filter <name>.\n"
+	      "If --smart-filter or --smart-filter-instance is specified,\n"
+	      "goes to the previous message that is similar to the current message.\n"
 	      "If --skip-deleted is specified, deleted messages will\n"
 	      "be skipped.\n"
@@ -366,5 +372,5 @@
   OWLCMD_ARGS("smartnarrow", owl_command_smartnarrow, OWL_CTX_INTERACTIVE,
 	      "view only messages similar to the current message",
-	      "smartnarrow [-i]",
+	      "smartnarrow [-i | --instance]",
 	      "If the curmsg is a personal message narrow\n"
 	      "   to the converstaion with that user.\n"
@@ -375,4 +381,15 @@
 	      "If the curmsg is a class message and '-i' is specied\n"
 	      "    then narrow to the class, instance\n"),
+
+  OWLCMD_ARGS("smartfilter", owl_command_smartfilter, OWL_CTX_INTERACTIVE,
+	      "returns the name of a filter based on the current message",
+	      "smartfilter [-i | --instance]",
+	      "If the curmsg is a personal message, the filter is\n"
+	      "   the converstaion with that user.\n"
+	      "If the curmsg is a class message, instance foo, recip *\n"
+	      "   message, the filter is the class, inst.\n"
+	      "If the curmsg is a class message, the filter is that class.\n"
+	      "If the curmsg is a class message and '-i' is specied\n"
+	      "    the filter is that <class,instance> pair\n"),
 
   OWLCMD_ARGS("viewclass", owl_command_viewclass, OWL_CTX_INTERACTIVE,
@@ -672,5 +689,11 @@
       argc-=1; argv+=1; 
     } else if (argc>=2 && !strcmp(argv[1], "--filter")) {
-      filter = argv[2];
+      filter = owl_strdup(argv[2]);
+      argc-=2; argv+=2; 
+    } else if (argc>=2 && !strcmp(argv[1], "--smart-filter")) {
+      filter = owl_function_smartfilter(0);
+      argc-=2; argv+=2; 
+    } else if (argc>=2 && !strcmp(argv[1], "--smart-filter-instance")) {
+      filter = owl_function_smartfilter(1);
       argc-=2; argv+=2; 
     } else {
@@ -680,4 +703,5 @@
   }
   owl_function_nextmsg_full(filter, skip_deleted, last_if_none);
+  if (filter) owl_free(filter);
   return(NULL);
 }
@@ -694,7 +718,13 @@
       argc-=1; argv+=1; 
     } else if (argc>=2 && !strcmp(argv[1], "--filter")) {
-      filter = argv[2];
+      filter = owl_strdup(argv[2]);
       argc-=2; argv+=2; 
-    } else {
+    } else if (argc>=2 && !strcmp(argv[1], "--smart-filter")) {
+      filter = owl_function_smartfilter(0);
+      argc-=2; argv+=2; 
+    } else if (argc>=2 && !strcmp(argv[1], "--smart-filter-instance")) {
+      filter = owl_function_smartfilter(1);
+      argc-=2; argv+=2;  
+   } else {
       owl_function_makemsg("Invalid arguments to command 'prev'.");
       return(NULL);
@@ -702,16 +732,36 @@
   }
   owl_function_prevmsg_full(filter, skip_deleted, first_if_none);
+  if (filter) owl_free(filter);
   return(NULL);
 }
 
 char *owl_command_smartnarrow(int argc, char **argv, char *buff) {
+  char *filtname = NULL;
+
   if (argc == 1) {
-    owl_function_smartnarrow(0);
-  } else if (argc == 2 && !strcmp(argv[1], "-i")) {
-    owl_function_smartnarrow(1);
+    filtname = owl_function_smartfilter(0);
+  } else if (argc == 2 && (!strcmp(argv[1], "-i") || !strcmp(argv[1], "--instance"))) {
+    filtname = owl_function_smartfilter(1);
   } else {
     owl_function_makemsg("Wrong number of arguments for %s", argv[0]);    
   }
-  return NULL;
+  if (filtname) {
+    owl_function_change_view(filtname);
+    owl_free(filtname);
+  }
+  return NULL;
+}
+
+char *owl_command_smartfilter(int argc, char **argv, char *buff) {
+  char *filtname = NULL;
+
+  if (argc == 1) {
+    filtname = owl_function_smartfilter(0);
+  } else if (argc == 2 && (!strcmp(argv[1], "-i") || !strcmp(argv[1], "--instance"))) {
+    filtname = owl_function_smartfilter(1);
+  } else {
+    owl_function_makemsg("Wrong number of arguments for %s", argv[0]);    
+  }
+  return filtname;
 }
 
@@ -1183,18 +1233,24 @@
 
 char *owl_command_viewclass(int argc, char **argv, char *buff) {
+  char *filtname;
   if (argc!=2) {
     owl_function_makemsg("Wrong number of arguments to viewclass command");
     return NULL;
   }
-  owl_function_fastclassinstfilt(argv[1], NULL);
+  filtname = owl_function_fastclassinstfilt(argv[1], NULL);
+  owl_function_change_view(filtname);
+  owl_free(filtname);
   return NULL;
 }
 
 char *owl_command_viewuser(int argc, char **argv, char *buff) {
+  char *filtname;
   if (argc!=2) {
     owl_function_makemsg("Wrong number of arguments to viewuser command");
     return NULL;
   }
-  owl_function_fastuserfilt(argv[1]);
+  filtname = owl_function_fastuserfilt(argv[1]);
+  owl_function_change_view(filtname);
+  owl_free(filtname);
   return NULL;
 }
@@ -1233,5 +1289,5 @@
   }
 
-  if (argc==3 && !strcmp(argv[1], "-id")) {
+  if (argc==3 && (!strcmp(argv[1], "-id") || !strcmp(argv[1], "--id"))) {
     owl_function_delete_by_id(atoi(argv[2]), 1);
     return NULL;
@@ -1261,5 +1317,5 @@
   }
 
-  if (argc==3 && !strcmp(argv[1], "-id")) {
+  if (argc==3 && (!strcmp(argv[1], "-id") || !strcmp(argv[1], "--id"))) {
     owl_function_delete_by_id(atoi(argv[2]), 0);
     return NULL;
Index: functions.c
===================================================================
--- functions.c	(revision 855ebe73d6ff7c3de47cb9b5c8dbd6b35a6974b4)
+++ functions.c	(revision 7360fabdd3382148cdd83b2bcb1ea86f19f02c94)
@@ -1683,7 +1683,8 @@
 }
 
-void owl_function_fastclassinstfilt(char *class, char *instance) {
-  /* narrow to the current class, instance.  If instance is null then
-     just narrow to the current class */
+char *owl_function_fastclassinstfilt(char *class, char *instance) {
+  /* creates a filter for a class, instance if one doesn't exist.
+   * If instance is null then apply for all messgaes in the class.
+   * returns the name of the filter, which the caller must free.*/
   owl_list *fl;
   owl_filter *f;
@@ -1706,7 +1707,5 @@
   /* if it already exists then go with it.  This lets users override */
   if (owl_global_get_filter(&g, filtname)) {
-    owl_function_change_view(filtname);
-    owl_free(filtname);
-    return;
+    return filtname;
   }
 
@@ -1724,12 +1723,9 @@
   owl_global_add_filter(&g, f);
 
-  /* set the current view to use it */
-  owl_function_change_view(filtname);
-
   owl_free(argbuff);
-  owl_free(filtname);
-}
-
-void owl_function_fastuserfilt(char *user) {
+  return filtname;
+}
+
+char *owl_function_fastuserfilt(char *user) {
   owl_filter *f;
   char *argbuff, *longuser, *shortuser, *filtname;
@@ -1745,7 +1741,5 @@
   /* if it already exists then go with it.  This lets users override */
   if (owl_global_get_filter(&g, filtname)) {
-    owl_function_change_view(filtname);
-    owl_free(filtname);
-    return;
+    return filtname;
   }
 
@@ -1763,13 +1757,10 @@
   owl_global_add_filter(&g, f);
 
-  /* set the current view to use it */
-  owl_function_change_view(filtname);
-
   /* free stuff */
   owl_free(argbuff);
-  owl_free(filtname);
   owl_free(longuser);
   owl_free(shortuser);
-    
+
+  return filtname;
 }
 
@@ -1795,17 +1786,19 @@
 }
 
-void owl_function_smartnarrow(int type) {
-  /* if the curmsg is a personal message narrow
+char *owl_function_smartfilter(int type) {
+  /* Returns the name of a filter, or null.  The caller 
+   * must free this name.  */
+  /* if the curmsg is a personal message return a filter name
    *    to the converstaion with that user.
    * If the curmsg is a class message, instance foo, recip *
-   *    message, narrow to the class, inst.
-   * If the curmsg is a class message and type==0 then narrow
-   *    to the class
-   * If the curmsg is a class message and type==1 then narrow
-   *    to the class, instance
+   *    message, return a filter name to the class, inst.
+   * If the curmsg is a class message and type==0 then 
+   *    return a filter name for just the class.
+   * If the curmsg is a class message and type==1 then 
+   *    return a filter name for the class and instance.
    */
   owl_view *v;
   owl_message *m;
-  char *sender;
+  char *sender, *filtname=NULL;
   
   v=owl_global_get_current_view(&g);
@@ -1814,5 +1807,5 @@
   if (owl_view_get_size(v)==0) {
     owl_function_makemsg("No message selected\n");
-    return;
+    return NULL;
   }
 
@@ -1820,5 +1813,5 @@
   if (owl_message_is_admin(m)) {
     owl_function_makemsg("Narrowing on an admin message has not been implemented yet.  Check back soon.");
-    return;
+    return NULL;
   }
 
@@ -1827,8 +1820,9 @@
     if (owl_message_is_zephyr(m)) {
       sender=pretty_sender(owl_message_get_sender(m));
-      owl_function_fastuserfilt(sender);
-      free(sender);
-    }
-    return;
+      filtname = owl_function_fastuserfilt(sender);
+      owl_free(sender);
+      return filtname;
+    }
+    return NULL;
   }
 
@@ -1836,14 +1830,15 @@
   if (!strcasecmp(owl_message_get_class(m), "message") &&
       !owl_message_is_personal(m)) {
-    owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
-    return;
+    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
+    return filtname;
   }
 
   /* otherwise narrow to the class */
   if (type==0) {
-    owl_function_fastclassinstfilt(owl_message_get_class(m), NULL);
+    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), NULL);
   } else if (type==1) {
-    owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
-  }
+    filtname = owl_function_fastclassinstfilt(owl_message_get_class(m), owl_message_get_instance(m));
+  }
+  return filtname;
 }
 
Index: keys.c
===================================================================
--- keys.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ keys.c	(revision 7360fabdd3382148cdd83b2bcb1ea86f19f02c94)
@@ -200,8 +200,10 @@
   BIND_CMD("DOWN",   "recv:next",      "");
   BIND_CMD("C-n",    "recv:next",      "");
+  BIND_CMD("M-C-n",  "recv:next --smart-filter", "move to next message matching the current one"); 
   BIND_CMD("UP",     "recv:prev",      "");
   BIND_CMD("n",      "recv:next-notdel", "");
   BIND_CMD("p",      "recv:prev-notdel", "");
   BIND_CMD("C-p",    "recv:prev",        "");
+  BIND_CMD("M-C-p",  "recv:prev --smart-filter", "move to previous message matching the current one");
   BIND_CMD("P",      "recv:next-personal", "");
   BIND_CMD("M-P",    "recv:prev-personal", "");
