Index: ChangeLog
===================================================================
--- ChangeLog	(revision 330bceca0874bd2c19a142ec9541e0ced544d19c)
+++ ChangeLog	(revision 3895e239d333afbb83de116f17028157a6b16008)
@@ -7,4 +7,7 @@
 	In the sepbar, reverse video the view name when it's not set to
 	  view_home (as opposed to the static 'all').
+	The '!' key (bound to 'view -r') now creates a negative version of
+	  the current view and switches to it.  i.e. "show me all the
+	  messages that are not these"
 	
 2.1.1-pre-2
Index: commands.c
===================================================================
--- commands.c	(revision 40458b9b76b4932dc25d63e99ae77aeaeb3ad646)
+++ commands.c	(revision 3895e239d333afbb83de116f17028157a6b16008)
@@ -548,5 +548,5 @@
   OWLCMD_ARGS("view", owl_command_view, OWL_CTX_INTERACTIVE,
 	      "view messages matching a filter",
-	      "view [<viewname>] [-f <filter> | --home ] [-s <style>]\n"
+	      "view [<viewname>] [-f <filter> | --home | -r ] [-s <style>]\n"
 	      "view <filter>\n"
 	      "view -d <expression>\n"
@@ -1226,5 +1226,5 @@
   }
   if (filtname) {
-    owl_function_change_view(filtname);
+    owl_function_change_currentview_filter(filtname);
     owl_free(filtname);
   }
@@ -1910,23 +1910,29 @@
 }
 
+
+/* Backwards compatability has made this kind of complicated:
+ * view [<viewname>] [-f <filter> | -d <expression> | --home | -r ] [-s <style>]
+ * view <filter>
+ * view -d <expression>
+ * view --home
+ */
 char *owl_command_view(int argc, char **argv, char *buff)
 {
-
-  /* Backwards compatability has made this kind of complicated:
-   * view [<viewname>] [-f <filter> | -d <expression> | --home ] [-s <style>]
-   * view <filter>
-   * view -d <expression>
-   * view --home
-   */
-
-  /* First take the 'view --home' case */
-  if (argc == 2 && !strcmp(argv[1], "--home")) {
-    owl_function_change_view(owl_global_get_view_home(&g));
-    return(NULL);
+  /* First take the 'view --home' and 'view -r' cases */
+  if (argc == 2) {
+    if (!strcmp(argv[1], "--home")) {
+      owl_function_change_currentview_filter(owl_global_get_view_home(&g));
+      return(NULL);
+    } else if (!strcmp(argv[1], "-r")) {
+      char *foo;
+      foo=owl_function_create_negative_filter(owl_view_get_filtname(owl_global_get_current_view(&g)));
+      owl_function_change_currentview_filter(foo);
+      return(NULL);
+    }
   }
 
   /* Now look for 'view <filter>' */
   if (argc==2) {
-    owl_function_change_view(argv[1]);
+    owl_function_change_currentview_filter(argv[1]);
     return(NULL);
   }
@@ -1944,5 +1950,5 @@
     }
     owl_function_create_filter(argc, myargv);
-    owl_function_change_view("owl-dynamic");
+    owl_function_change_currentview_filter("owl-dynamic");
     owl_free(myargv);
     return NULL;
@@ -1956,5 +1962,9 @@
   argc--;
   argv++;
-  if (strcmp(argv[0], "-f") && strcmp(argv[0], "-d") && strcmp(argv[0], "--home") && strcmp(argv[0], "-s")) {
+  if (strcmp(argv[0], "-f") &&
+      strcmp(argv[0], "-d") &&
+      strcmp(argv[0], "--home") &&
+      strcmp(argv[0], "-s") &&
+      strcmp(argv[0], "-r")) {
     if (strcmp(argv[0], "main")) {
       owl_function_makemsg("No view named '%s'", argv[0]);
@@ -1970,11 +1980,15 @@
 	return(NULL);
       }
-      owl_function_change_view(argv[1]);
+      owl_function_change_currentview_filter(argv[1]);
       argc-=2;
       argv+=2;
     } else if (!strcmp(argv[0], "--home")) {
-      owl_function_change_view(owl_global_get_view_home(&g));
+      owl_function_change_currentview_filter(owl_global_get_view_home(&g));
       argc--;
       argv++;
+    } else if (!strcmp(argv[0], "-r")) {
+      char *foo;
+      foo=owl_function_create_negative_filter(owl_view_get_filtname(owl_global_get_current_view(&g)));
+      owl_function_change_currentview_filter(foo);
     } else if (!strcmp(argv[0], "-s")) {
       if (argc<2) {
@@ -2069,5 +2083,5 @@
   }
   filtname = owl_function_classinstfilt(argv[1], NULL);
-  owl_function_change_view(filtname);
+  owl_function_change_currentview_filter(filtname);
   owl_free(filtname);
   return NULL;
@@ -2082,5 +2096,5 @@
   }
   filtname=owl_function_zuserfilt(argv[1]);
-  owl_function_change_view(filtname);
+  owl_function_change_currentview_filter(filtname);
   owl_free(filtname);
   return NULL;
Index: functions.c
===================================================================
--- functions.c	(revision 40458b9b76b4932dc25d63e99ae77aeaeb3ad646)
+++ functions.c	(revision 3895e239d333afbb83de116f17028157a6b16008)
@@ -2250,6 +2250,5 @@
 }
 
-#if 0
-void owl_function_change_view_old(char *filtname)
+void owl_function_change_currentview_filter(char *filtname)
 {
   owl_view *v;
@@ -2259,4 +2258,5 @@
 
   v=owl_global_get_current_view(&g);
+
   curmsg=owl_global_get_curmsg(&g);
   if (curmsg==-1) {
@@ -2270,5 +2270,4 @@
   }
 
-  /* grab the filter */;
   f=owl_global_get_filter(&g, filtname);
   if (!f) {
@@ -2277,7 +2276,5 @@
   }
 
-  /* free the existing view and create a new one based on the filter */
-  owl_view_free(v);
-  owl_view_create(v, f);
+  owl_view_new_filter(v, f);
 
   /* Figure out what to set the current message to.
@@ -2293,55 +2290,8 @@
 
   owl_global_set_curmsg(&g, newpos);
-
   owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
   owl_mainwin_redisplay(owl_global_get_mainwin(&g));
   owl_global_set_direction_downwards(&g);
 }
-#endif
-
-void owl_function_change_view(char *filtname)
-{
-  owl_view *v;
-  owl_filter *f;
-  int curid=-1, newpos, curmsg;
-  owl_message *curm=NULL;
-
-  v=owl_global_get_current_view(&g);
-
-  curmsg=owl_global_get_curmsg(&g);
-  if (curmsg==-1) {
-    owl_function_debugmsg("Hit the curmsg==-1 case in change_view");
-  } else {
-    curm=owl_view_get_element(v, curmsg);
-    if (curm) {
-      curid=owl_message_get_id(curm);
-      owl_view_save_curmsgid(v, curid);
-    }
-  }
-
-  f=owl_global_get_filter(&g, filtname);
-  if (!f) {
-    owl_function_error("Unknown filter %s", filtname);
-    return;
-  }
-
-  owl_view_new_filter(v, f);
-
-  /* Figure out what to set the current message to.
-   * - If the view we're leaving has messages in it, go to the closest message
-   *   to the last message pointed to in that view. 
-   * - If the view we're leaving is empty, try to restore the position
-   *   from the last time we were in the new view.  */
-  if (curm) {
-    newpos = owl_view_get_nearest_to_msgid(v, curid);
-  } else {
-    newpos = owl_view_get_nearest_to_saved(v);
-  }
-
-  owl_global_set_curmsg(&g, newpos);
-  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
-  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
-  owl_global_set_direction_downwards(&g);
-}
 
 void owl_function_create_filter(int argc, char **argv)
@@ -2355,4 +2305,6 @@
     return;
   }
+
+  owl_function_debugmsg("owl_function_create_filter: starting to create filter named %s", argv[1]);
 
   v=owl_global_get_current_view(&g);
@@ -2405,8 +2357,45 @@
   /* if it was in use by the current view then update */
   if (inuse) {
-    owl_function_change_view(argv[1]);
+    owl_function_change_currentview_filter(argv[1]);
   }
   owl_global_set_needrefresh(&g);
   owl_mainwin_redisplay(owl_global_get_mainwin(&g));
+}
+
+/* If 'filtername' does not start with 'not-' create a filter named
+ * 'not-<filtername>' defined as "not filter <filtername>".  If the
+ * filter 'not-<filtername>' already exists, do not overwrite it.  If
+ * 'filtername' begins with 'not-' and a filter 'filtername' already
+ * exists, then do nothing.  If the filter 'filtername' does not
+ * exist, create it and define it as 'not filter <filtername>'
+ *
+ * Returns the name of the negated filter, which the caller must free.
+ */
+char *owl_function_create_negative_filter(char *filtername)
+{
+  char *newname;
+  owl_filter *tmpfilt;
+  char *argv[5];
+
+  owl_function_debugmsg("owl_function_create_negative_filter");
+  
+  if (!strncmp(filtername, "not-", 4)) {
+    newname=owl_strdup(filtername+4);
+  } else {
+    newname=owl_sprintf("not-%s", filtername);
+  }
+
+  tmpfilt=owl_global_get_filter(&g, newname);
+  if (!tmpfilt) {
+    argv[0]="filter"; /* anything is fine here */
+    argv[1]=newname;
+    argv[2]="not";
+    argv[3]="filter";
+    argv[4]=filtername;
+    owl_function_create_filter(5, argv);
+  }
+
+  owl_function_debugmsg("owl_function_create_negative_filter: returning with %s", newname);
+  return(newname);
 }
 
Index: help.c
===================================================================
--- help.c	(revision 15283bb262a596e38cf9c59b498670211458c33d)
+++ help.c	(revision 3895e239d333afbb83de116f17028157a6b16008)
@@ -59,4 +59,5 @@
      "    V             Change to back to home view ('all' by default)\n"
      "    v             Start a view command\n"
+     "    !             Invert the current view\n"
      "\n"
      "    l             Print a zephyr/AIM buddy listing\n"
Index: keys.c
===================================================================
--- keys.c	(revision 8b164678b2661dc1c9f60c079e43480dd13d2f60)
+++ keys.c	(revision 3895e239d333afbb83de116f17028157a6b16008)
@@ -218,4 +218,5 @@
   BIND_CMD("v",   "start-command view ", "start a view command");
   BIND_CMD("V",   "view --home",      "change to the home view ('all' by default)");
+  BIND_CMD("!",   "view -r",          "invert the current view filter");
   BIND_CMD("M-n", "smartnarrow",      "narrow to a view based on the current message");
   BIND_CMD("M-N", "smartnarrow -i",   "narrow to a view based on the current message, and consider instance pair");
