Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ ChangeLog	(revision b9500884ebb34781929664a20fd81a6a0c8b867c)
@@ -5,4 +5,17 @@
 	Added RCS Id strings to all files.
 	'show keymaps' shows details of all keymaps after summary list.
+	Added --no-move option to delete command.
+	        In particular, delete-and-always-move-down may now
+		be implemented with 
+		'( delete --no-move ; next --skip-deleted )'.
+	Folded the nextmsg and prevmsg commands and functions together into 
+	        one command which takes arguments.
+		Added '--filter <name>' option (eg, for next_personal),
+		'--skip-deleted' option, and
+		'--last-if-none'/'--first-if-none' options.
+		Help updated accordingly.  
+		In particular, the 'personal' view is now used 
+		for 'next personal'.  
+	Updated examples/owlconf.erik with the above.
 	
 1.2.0-pre-erikdevel-17
Index: commands.c
===================================================================
--- commands.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ commands.c	(revision b9500884ebb34781929664a20fd81a6a0c8b867c)
@@ -193,27 +193,37 @@
 	      "Scrolls up if <numlines> is negative, else scrolls down.\n"),
 
-  OWLCMD_VOID("next", owl_command_next, OWL_CTX_INTERACTIVE,
-	      "move the pointer to the next message", "", ""),
+  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 ]",
+	      "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 --skip-deleted is specified, deleted messages will\n"
+	      "be skipped.\n"
+	      "If --last-if-none is specified, will stop at last message\n"
+	      "in the view if no other suitable messages are found.\n"),
   OWLCMD_ALIAS("recv:next", "next"),
 
-  OWLCMD_VOID("prev", owl_command_prev, OWL_CTX_INTERACTIVE,
-	      "move the pointer to the previous message", "", ""),
+  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 ]",
+	      "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 --skip-deleted is specified, deleted messages will\n"
+	      "be skipped.\n"
+	      "If --first-if-none is specified, will stop at first message\n"
+	      "in the view if no other suitable messages are found.\n"),
   OWLCMD_ALIAS("recv:prev", "prev"),
 
-  OWLCMD_VOID("next-notdel", owl_command_next_notdeleted, OWL_CTX_INTERACTIVE,
-	      "move the pointer to the next non-deleted message", "", ""),
-  OWLCMD_ALIAS("recv:next-notdel", "next-notdel"),
-
-  OWLCMD_VOID("prev-notdel", owl_command_prev_notdeleted, OWL_CTX_INTERACTIVE,
-	      "move the pointer to the previous non-deleted message", "", ""),
-  OWLCMD_ALIAS("recv:prev-notdel", "prev-notdel"),
-
-  OWLCMD_VOID("recv:next-personal", owl_function_next_personal, 
-	      OWL_CTX_INTERACTIVE,
-	      "move the pointer to the next personal message", "", ""),
-
-  OWLCMD_VOID("recv:prev-personal", owl_function_prev_personal, 
-	      OWL_CTX_INTERACTIVE,
-	      "move the pointer to the previous personal message", "", ""),
+  OWLCMD_ALIAS("recv:next-notdel", "recv:next --skip-deleted --last-if-none"),
+  OWLCMD_ALIAS("next-notdel",      "recv:next --skip-deleted --last-if-none"),
+
+  OWLCMD_ALIAS("recv:prev-notdel", "recv:prev --skip-deleted --first-if-none"),
+  OWLCMD_ALIAS("prev-notdel",      "recv:prev --skip-deleted --first-if-none"),
+
+  OWLCMD_ALIAS("recv:next-personal", "recv:next --filter personal"),
+
+  OWLCMD_ALIAS("recv:prev-personal", "recv:prev --filter personal"),
 
   OWLCMD_VOID("first", owl_command_first, OWL_CTX_INTERACTIVE,
@@ -417,5 +427,5 @@
   OWLCMD_ARGS("delete", owl_command_delete, OWL_CTX_INTERACTIVE,
 	      "mark a message for deletion",
-	      "delete [ -id msgid ]\n"
+	      "delete [ -id msgid ] [ --no-move ]\n"
 	      "delete view\n"
 	      "delete trash",
@@ -423,4 +433,5 @@
 	      "for deletion.  Otherwise the message with the given message\n"
 	      "id is marked for deltion.\n"
+	      "If '--no-move' is specified, don't move after deletion.\n"
 	      "If 'trash' is specified, deletes all trash/auto messages\n"
 	      "in the current view.\n"
@@ -431,9 +442,10 @@
   OWLCMD_ARGS("undelete", owl_command_undelete, OWL_CTX_INTERACTIVE,
 	      "unmark a message for deletion",
-	      "undelete [ -id msgid ]\n"
+	      "undelete [ -id msgid ] [ --no-move ]\n"
 	      "undelete view",
 	      "If no message id is specified the current message is\n"
 	      "unmarked for deletion.  Otherwise the message with the\n"
 	      "given message id is marked for undeltion.\n"
+	      "If '--no-move' is specified, don't move after deletion.\n"
 	      "If 'view' is specified, undeletes all messages\n"
 	      "in the current view.\n"),
@@ -649,18 +661,46 @@
 }
 
-void owl_command_next() {
-  owl_function_nextmsg();
-}
-
-void owl_command_prev() {
-  owl_function_prevmsg();
-}
-
-void owl_command_next_notdeleted() {
-  owl_function_nextmsg_notdeleted();
-}
-
-void owl_command_prev_notdeleted() {
-  owl_function_prevmsg_notdeleted();
+char *owl_command_next(int argc, char **argv, char *buff) {
+  char *filter=NULL;
+  int skip_deleted=0, last_if_none=0;
+  while (argc>1) {
+    if (argc>=1 && !strcmp(argv[1], "--skip-deleted")) {
+      skip_deleted=1;
+      argc-=1; argv+=1; 
+    } else if (argc>=1 && !strcmp(argv[1], "--last-if-none")) {
+      last_if_none=1;
+      argc-=1; argv+=1; 
+    } else if (argc>=2 && !strcmp(argv[1], "--filter")) {
+      filter = argv[2];
+      argc-=2; argv+=2; 
+    } else {
+      owl_function_makemsg("Invalid arguments to command 'next'.");
+      return(NULL);
+    }
+  }
+  owl_function_nextmsg_full(filter, skip_deleted, last_if_none);
+  return(NULL);
+}
+
+char *owl_command_prev(int argc, char **argv, char *buff) {
+  char *filter=NULL;
+  int skip_deleted=0, first_if_none=0;
+  while (argc>1) {
+    if (argc>=1 && !strcmp(argv[1], "--skip-deleted")) {
+      skip_deleted=1;
+      argc-=1; argv+=1; 
+    } else if (argc>=1 && !strcmp(argv[1], "--first-if-none")) {
+      first_if_none=1;
+      argc-=1; argv+=1; 
+    } else if (argc>=2 && !strcmp(argv[1], "--filter")) {
+      filter = argv[2];
+      argc-=2; argv+=2; 
+    } else {
+      owl_function_makemsg("Invalid arguments to command 'prev'.");
+      return(NULL);
+    }
+  }
+  owl_function_prevmsg_full(filter, skip_deleted, first_if_none);
+  return(NULL);
 }
 
@@ -1170,6 +1210,14 @@
 
 char *owl_command_delete(int argc, char **argv, char *buff) {
+  int move_after = 1;
+
+  if (!strcmp(argv[1], "--no-move")) {
+    move_after = 0;
+    argc--; 
+    argv++;
+  }
+
   if (argc==1) {
-    owl_function_deletecur();
+    owl_function_deletecur(move_after);
     return NULL;
   }
@@ -1195,6 +1243,14 @@
 
 char *owl_command_undelete(int argc, char **argv, char *buff) {
+  int move_after = 1;
+
+  if (!strcmp(argv[1], "--no-move")) {
+    move_after = 0;
+    argc--; 
+    argv++;
+  }
+
   if (argc==1) {
-    owl_function_undeletecur();
+    owl_function_undeletecur(move_after);
     return NULL;
   }
Index: examples/owlconf.erik
===================================================================
--- examples/owlconf.erik	(revision 7d4fbcdd0df83802711454fdafce2c9d592bf431)
+++ examples/owlconf.erik	(revision b9500884ebb34781929664a20fd81a6a0c8b867c)
@@ -1,4 +1,13 @@
 ### The owlconf config file   -*- perl -*-  
 ###  $Id$
+
+### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!!
+### This is an example file intended to demonstrate how to use 
+### various features of owl.  Some of the key bindings, in particular,
+### are more for examples than things you may actually want to use.
+### Make sure to read through it first and understand it before just using it.
+### Don't blame me if anything in here ends up vaporizing your dog.
+### !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!! !!!!!WARNING!!!!!
+
 ###
 ### This file is interpreted by the perl interpreter.
@@ -77,8 +86,18 @@
     owl::command("alias zc zwrite -c");
 
+    # Send zephyrs with "C-c C-c".  
+    # Note that this will cause "C-c" to not work...
     owl::command("bindkey editmulti \"C-c C-c\" command editmulti:done");
+
+    # Make "d" ignore current movement direction
+    owl::command("bindkey recv d command ( delete --no-move ; next --skip-deleted )");
+
+    # Useful keys for reading and deleting by class/instance
     owl::command("bindkey recv M-k command ( smartnarrow ; delete view )");
     owl::command("bindkey recv M-l command ( expunge ; view all )");
     owl::command("bindkey recv M-K command ( smartnarrow ; delete view ; expunge ; view all )");
+
+    # Make 'M-s' insert a <scritchscritchscritch> sequence with a random
+    # number of scritches.
     owl::command(q(bindkey edit M-s command perl owl::command("edit:insert-text <".("scritch"x int(1+rand(5))).">")));
 
Index: functions.c
===================================================================
--- functions.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ functions.c	(revision b9500884ebb34781929664a20fd81a6a0c8b867c)
@@ -176,110 +176,136 @@
 
 
+/* If filter is non-null, looks for the next message matching
+ * that filter.  If skip_deleted, skips any deleted messages. 
+ * If last_if_none, will stop at the last message in the view
+ * if no matching messages are found.  */
+void owl_function_nextmsg_full(char *filter, int skip_deleted, int last_if_none) {
+  int curmsg, i, viewsize, found;
+  owl_view *v;
+  owl_filter *f = NULL;
+  owl_message *m;
+
+  v=owl_global_get_current_view(&g);
+
+  if (filter) {
+    f=owl_global_get_filter(&g, filter);
+    if (!f) {
+      owl_function_makemsg("No %s filter defined", filter);
+      return;
+    }
+  }
+
+  curmsg=owl_global_get_curmsg(&g);
+  viewsize=owl_view_get_size(v);
+  found=0;
+
+  /* just check to make sure we're in bounds... */
+  if (curmsg>viewsize-1) curmsg=viewsize-1;
+  if (curmsg<0) curmsg=0;
+
+  for (i=curmsg+1; i<viewsize; i++) {
+    m=owl_view_get_element(v, i);
+    if (skip_deleted && owl_message_is_delete(m)) continue;
+    if (f && !owl_filter_message_match(f, m)) continue;
+    found = 1;
+    break;
+  }
+
+  if (i>owl_view_get_size(v)-1) i=owl_view_get_size(v)-1;
+
+  if (!found) {
+    owl_function_makemsg("already at last%s message%s%s",
+			 skip_deleted?" non-deleted":"",
+			 filter?" in ":"", filter?filter:"");
+    owl_function_beep();
+  }
+
+  if (last_if_none || found) {
+    owl_global_set_curmsg(&g, i);
+    owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
+    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
+    owl_global_set_direction_downwards(&g);
+  }
+}
+
+void owl_function_prevmsg_full(char *filter, int skip_deleted, int first_if_none) {
+  int curmsg, i, viewsize, found;
+  owl_view *v;
+  owl_filter *f = NULL;
+  owl_message *m;
+
+  v=owl_global_get_current_view(&g);
+
+  if (filter) {
+    f=owl_global_get_filter(&g, filter);
+    if (!f) {
+      owl_function_makemsg("No %s filter defined", filter);
+      return;
+    }
+  }
+
+  curmsg=owl_global_get_curmsg(&g);
+  viewsize=owl_view_get_size(v);
+  found=0;
+
+  /* just check to make sure we're in bounds... */
+  if (curmsg>viewsize-1) curmsg=viewsize-1;
+  if (curmsg<0) curmsg=0;
+
+  for (i=curmsg-1; i>=0; i--) {
+    m=owl_view_get_element(v, i);
+    if (skip_deleted && owl_message_is_delete(m)) continue;
+    if (f && !owl_filter_message_match(f, m)) continue;
+    found = 1;
+    break;
+  }
+
+  if (i<0) i=0;
+
+  if (!found) {
+    owl_function_makemsg("already at first%s message%s%s",
+			 skip_deleted?" non-deleted":"",
+			 filter?" in ":"", filter?filter:"");
+    owl_function_beep();
+  }
+
+  if (first_if_none || found) {
+    owl_global_set_curmsg(&g, i);
+    owl_function_calculate_topmsg(OWL_DIRECTION_UPWARDS);
+    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
+    owl_global_set_direction_upwards(&g);
+  }
+}
 
 void owl_function_nextmsg() {
-  int curmsg;
-  owl_view *v;
-
-  v=owl_global_get_current_view(&g);
-  
-  curmsg=owl_global_get_curmsg(&g);
-  curmsg++;
-  if (curmsg>owl_view_get_size(v)-1) {
-    curmsg=owl_view_get_size(v)-1;
-    if (curmsg<0) curmsg=0;
-    owl_function_beep();
-    owl_function_makemsg("already at last message");
-  }
-  owl_global_set_curmsg(&g, curmsg);
-  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
-
-  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-  owl_global_set_direction_downwards(&g);
+  owl_function_nextmsg_full(NULL, 0, 1);
 }
 
 
 void owl_function_prevmsg() {
-  int curmsg;
-  
-  curmsg=owl_global_get_curmsg(&g);
-  curmsg--;
-  if (curmsg<0) {
-    curmsg=0;
-    owl_function_beep();
-    owl_function_makemsg("already at first message");
-  }
-  owl_global_set_curmsg(&g, curmsg);
-  owl_function_calculate_topmsg(OWL_DIRECTION_UPWARDS);
-  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-  owl_global_set_direction_upwards(&g);
-}
-
+  owl_function_prevmsg_full(NULL, 0, 1);
+}
 
 void owl_function_nextmsg_notdeleted() {
-  int curmsg;
-  owl_message *m;
-  owl_view *v;
-
-  v=owl_global_get_current_view(&g);
-
-  curmsg=owl_global_get_curmsg(&g);
-  while (1) {
-    curmsg++;
-
-    /* if we're out of bounds get in bounds and stop */
-    if (curmsg>owl_view_get_size(v)-1) {
-      curmsg=owl_view_get_size(v)-1;
-      if (curmsg<0) curmsg=0;
-      owl_function_makemsg("already at last non-deleted message");
-      break;
-    }
-
-    /* if this one is not deleted we can stop where we are */
-    m=owl_view_get_element(v, curmsg);
-    if (!owl_message_is_delete(m)) {
-      break;
-    }
-  }
-  
-  owl_global_set_curmsg(&g, curmsg);
-  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
-  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-  owl_global_set_direction_downwards(&g);
+  owl_function_nextmsg_full(NULL, 1, 1);
 }
 
 
 void owl_function_prevmsg_notdeleted() {
-  int curmsg;
-  owl_message *m;
-  owl_view *v;
-
-  v=owl_global_get_current_view(&g);
-
-  curmsg=owl_global_get_curmsg(&g);
-  while(1) {
-    curmsg--;
-
-    /* if we're out of bounds get in bounds and stop */
-    if (curmsg<0) {
-      curmsg=0;
-      owl_function_makemsg("already at first non-deleted message");
-      break;
-    }
-
-    /* if this one is not deleted we can stop where we are */
-    m=owl_view_get_element(v, curmsg);
-    if (!owl_message_is_delete(m)) {
-      break;
-    }
-  }
-
-  owl_global_set_curmsg(&g, curmsg);
-  owl_function_calculate_topmsg(OWL_DIRECTION_UPWARDS);
-  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-  owl_global_set_direction_upwards(&g);
-}
-
-
-void owl_function_deletecur() {
+  owl_function_prevmsg_full(NULL, 1, 1);
+}
+
+
+void owl_function_nextmsg_personal() {
+  owl_function_nextmsg_full("personal", 0, 0);
+}
+
+void owl_function_prevmsg_personal() {
+  owl_function_prevmsg_full("personal", 0, 0);
+}
+
+
+/* if move_after is 1, moves after the delete */
+void owl_function_deletecur(int move_after) {
   int curmsg;
   owl_view *v;
@@ -297,14 +323,17 @@
   owl_view_delete_element(v, curmsg);
 
-  /* move the poiner in the appropriate direction to the next undeleted msg */
-  if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
-    owl_command_prev_notdeleted();
-  } else {
-    owl_command_next_notdeleted();
-  }
-}
-
-
-void owl_function_undeletecur() {
+  if (move_after) {
+    /* move the poiner in the appropriate direction 
+     * to the next undeleted msg */
+    if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
+      owl_function_prevmsg_notdeleted();
+    } else {
+      owl_function_nextmsg_notdeleted();
+    }
+  }
+}
+
+
+void owl_function_undeletecur(int move_after) {
   int curmsg;
   owl_view *v;
@@ -320,12 +349,14 @@
   owl_view_undelete_element(v, curmsg);
 
-  if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
-    if (curmsg>0) {
-      owl_command_prev();
+  if (move_after) {
+    if (owl_global_get_direction(&g)==OWL_DIRECTION_UPWARDS) {
+      if (curmsg>0) {
+	owl_function_prevmsg();
+      } else {
+	owl_function_nextmsg();
+      }
     } else {
-      owl_command_next();
-    }
-  } else {
-    owl_command_next();
+      owl_function_nextmsg();
+    }
   }
 
@@ -1259,49 +1290,4 @@
   owl_function_makemsg(buff);
   owl_global_set_needrefresh(&g);
-}
-
-void owl_function_next_personal() {
-  int i, j, curmsg, found;
-  owl_view *v;
-
-  v=owl_global_get_current_view(&g);
-  j=owl_view_get_size(v);
-  curmsg=owl_global_get_curmsg(&g);
-  found=0;
-  for (i=curmsg+1; i<j; i++) {
-    if (owl_message_is_personal(owl_view_get_element(v, i))) {
-      owl_global_set_curmsg(&g, i);
-      owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
-      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-      owl_global_set_direction_downwards(&g);
-      found=1;
-      break;
-    }
-  }
-  if (!found) {
-    owl_function_makemsg("No next personal message found");
-  }
-}
-
-void owl_function_prev_personal() {
-  int i, curmsg, found;
-  owl_view *v;
-
-  v=owl_global_get_current_view(&g);
-  curmsg=owl_global_get_curmsg(&g);
-  found=0;
-  for (i=curmsg-1; i>=0; i--) {
-    if (owl_message_is_personal(owl_view_get_element(v, i))) {
-      owl_global_set_curmsg(&g, i);
-      owl_function_calculate_topmsg(OWL_DIRECTION_UPWARDS);
-      owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-      owl_global_set_direction_upwards(&g);
-      found=1;
-      break;
-    }
-  }
-  if (!found) {
-    owl_function_makemsg("No previous personal message found");
-  }
 }
 
