(SWITCH_ENUM_CAST): New macro.
[bpt/emacs.git] / src / callint.c
index ffa2fa3..3de79be 100644 (file)
@@ -1,5 +1,5 @@
 /* Call a Lisp function interactively.
-   Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,7 +18,7 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "buffer.h"
 #include "commands.h"
@@ -28,13 +28,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 extern char *index ();
 
-Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus;
+Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus, Qplus;
 Lisp_Object Qcall_interactively;
 Lisp_Object Vcommand_history;
 
 Lisp_Object Vcommand_debug_status, Qcommand_debug_status;
 Lisp_Object Qenable_recursive_minibuffers;
 
+/* Non-nil means treat the mark as active
+   even if mark_active is 0.  */
+Lisp_Object Vmark_even_if_inactive;
+
+Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook;
+
 Lisp_Object Qlist;
 Lisp_Object preserved_fns;
 
@@ -69,15 +75,15 @@ c -- Character.\n\
 C -- Command name: symbol with interactive function definition.\n\
 d -- Value of point as number.  Does not do I/O.\n\
 D -- Directory name.\n\
-e -- Event that invoked this command (value of `last-nonmenu-event').\n\
-     This skips events without parameters.\n\
-     If used more than once, the Nth 'e' returns the Nth parameterized event.\n\
+e -- Parametrized event (i.e., one that's a list) that invoked this command.\n\
+     If used more than once, the Nth `e' returns the Nth parameterized event.\n\
+     This skips events that are integers or symbols.\n\
 f -- Existing file name.\n\
 F -- Possibly nonexistent file name.\n\
 k -- Key sequence (string).\n\
 m -- Value of mark as number.  Does not do I/O.\n\
 n -- Number read using minibuffer.\n\
-N -- Prefix arg converted to number, or if none, do like code `n'.\n\
+N -- Raw prefix arg, or if none, do like code `n'.\n\
 p -- Prefix arg converted to number.  Does not do I/O.\n\
 P -- Prefix arg in raw form.  Does not do I/O.\n\
 r -- Region: point and mark as 2 numeric args, smallest first.  Does no I/O.\n\
@@ -110,7 +116,7 @@ Lisp_Object
 quotify_arg (exp)
      register Lisp_Object exp;
 {
-  if (XTYPE (exp) != Lisp_Int && XTYPE (exp) != Lisp_String
+  if (!INTEGERP (exp) && !STRINGP (exp)
       && !NILP (exp) && !EQ (exp, Qt))
     return Fcons (Qquote, Fcons (exp, Qnil));
 
@@ -138,9 +144,13 @@ char *callint_argfuns[]
 static void
 check_mark ()
 {
-  Lisp_Object tem = Fmarker_buffer (current_buffer->mark);
+  Lisp_Object tem;
+  tem = Fmarker_buffer (current_buffer->mark);
   if (NILP (tem) || (XBUFFER (tem) != current_buffer))
     error ("The mark is not set now");
+  if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
+      && NILP (current_buffer->mark_active))
+    Fsignal (Qmark_inactive, Qnil);
 }
 
 
@@ -192,7 +202,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
 
  retry:
 
-  if (XTYPE (function) == Lisp_Symbol)
+  if (SYMBOLP (function))
     enable = Fget (function, Qenable_recursive_minibuffers);
 
   fun = indirect_function (function);
@@ -204,22 +214,22 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
      or go to `lose' if not interactive, or go to `retry'
      to specify a different function, or set either STRING or SPECS.  */
 
-  if (XTYPE (fun) == Lisp_Subr)
+  if (SUBRP (fun))
     {
       string = (unsigned char *) XSUBR (fun)->prompt;
       if (!string)
        {
        lose:
-         function = wrong_type_argument (Qcommandp, function, 0);
+         function = wrong_type_argument (Qcommandp, function);
          goto retry;
        }
-      if ((int) string == 1)
+      if ((EMACS_INT) string == 1)
        /* Let SPECS (which is nil) be used as the args.  */
        string = 0;
     }
-  else if (XTYPE (fun) == Lisp_Compiled)
+  else if (COMPILEDP (fun))
     {
-      if (XVECTOR (fun)->size <= COMPILED_INTERACTIVE)
+      if ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_INTERACTIVE)
        goto lose;
       specs = XVECTOR (fun)->contents[COMPILED_INTERACTIVE];
     }
@@ -245,7 +255,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
     goto lose;
 
   /* If either specs or string is set to a string, use it.  */
-  if (XTYPE (specs) == Lisp_String)
+  if (STRINGP (specs))
     {
       /* Make a copy of string so that if a GC relocates specs,
         `string' will still be valid.  */
@@ -303,7 +313,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
        (XVECTOR (this_command_keys)->contents[next_event]))
       break;
   
-  /* Handle special starting chars `*' and `@'.  */
+  /* Handle special starting chars `*' and `@'.  Also `-'.  */
   while (1)
     {
       if (*string == '*')
@@ -312,16 +322,29 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
          if (!NILP (current_buffer->read_only))
            Fbarf_if_buffer_read_only ();
        }
+      /* Ignore this for semi-compatibility with Lucid.  */
+      else if (*string == '-')
+       string++;
       else if (*string == '@')
        {
-         Lisp_Object event =
-           XVECTOR (this_command_keys)->contents[next_event];
+         Lisp_Object event;
 
+         event = XVECTOR (this_command_keys)->contents[next_event];
          if (EVENT_HAS_PARAMETERS (event)
-             && XTYPE (event = XCONS (event)->cdr) == Lisp_Cons
-             && XTYPE (event = XCONS (event)->car) == Lisp_Cons
-             && XTYPE (event = XCONS (event)->car) == Lisp_Window)
-           Fselect_window (event);
+             && (event = XCONS (event)->car, CONSP (event))
+             && (event = XCONS (event)->car, CONSP (event))
+             && (event = XCONS (event)->car), WINDOWP (event))
+           {
+             if (MINI_WINDOW_P (XWINDOW (event))
+                 && ! (minibuf_level > 0 && EQ (event, minibuf_window)))
+               error ("Attempt to select inactive minibuffer window");
+
+             /* If the current buffer wants to clean up, let it.  */
+             if (!NILP (Vmouse_leave_buffer_hook))
+               call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
+
+             Fselect_window (event);
+           }
          string++;
        }
       else break;
@@ -419,7 +442,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
          break;
 
        case 'd':               /* Value of point.  Does not do I/O.  */
-         XFASTINT (args[i]) = point;
+         XSETFASTINT (args[i], point);
          /* visargs[i] = Qnil; */
          varies[i] = 1;
          break;
@@ -448,7 +471,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
        case 'e':               /* The invoking event.  */
          if (next_event >= this_command_key_count)
            error ("%s must be bound to an event with parameters",
-                  (XTYPE (function) == Lisp_Symbol
+                  (SYMBOLP (function)
                    ? (char *) XSYMBOL (function)->name->data
                    : "command"));
          args[i] = XVECTOR (this_command_keys)->contents[next_event++];
@@ -465,7 +488,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
        case 'm':               /* Value of mark.  Does not do I/O.  */
          check_mark ();
          /* visargs[i] = Qnil; */
-         XFASTINT (args[i]) = marker_position (current_buffer->mark);
+         XSETFASTINT (args[i], marker_position (current_buffer->mark));
          varies[i] = 2;
          break;
 
@@ -497,9 +520,9 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
          /* visargs[i+1] = Qnil; */
          foo = marker_position (current_buffer->mark);
          /* visargs[i] = Qnil; */
-         XFASTINT (args[i]) = point < foo ? point : foo;
+         XSETFASTINT (args[i], point < foo ? point : foo);
          varies[i] = 3;
-         XFASTINT (args[++i]) = point > foo ? point : foo;
+         XSETFASTINT (args[++i], point > foo ? point : foo);
          varies[i] = 4;
          break;
 
@@ -538,7 +561,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
       if (varies[i] == 0)
        arg_from_tty = 1;
 
-      if (NILP (visargs[i]) && XTYPE (args[i]) == Lisp_String)
+      if (NILP (visargs[i]) && STRINGP (args[i]))
        visargs[i] = args[i];
 
       tem = (unsigned char *) index (tem, '\n');
@@ -583,20 +606,16 @@ Its numeric meaning is what you would get from `(interactive \"p\")'.")
 {
   Lisp_Object val;
   
-  /* Tag val as an integer, so the rest of the assignments
-     may use XSETINT.  */
-  XFASTINT (val) = 0;
-
   if (NILP (raw))
-    XFASTINT (val) = 1;
+    XSETFASTINT (val, 1);
   else if (EQ (raw, Qminus))
     XSETINT (val, -1);
   else if (CONSP (raw))
     XSETINT (val, XINT (XCONS (raw)->car));
-  else if (XTYPE (raw) == Lisp_Int)
+  else if (INTEGERP (raw))
     val = raw;
   else
-    XFASTINT (val) = 1;
+    XSETFASTINT (val, 1);
 
   return val;
 }
@@ -615,6 +634,9 @@ syms_of_callint ()
   Qminus = intern ("-");
   staticpro (&Qminus);
 
+  Qplus = intern ("+");
+  staticpro (&Qplus);
+
   Qcall_interactively = intern ("call-interactively");
   staticpro (&Qcall_interactively);
 
@@ -624,6 +646,9 @@ syms_of_callint ()
   Qenable_recursive_minibuffers = intern ("enable-recursive-minibuffers");
   staticpro (&Qenable_recursive_minibuffers);
 
+  Qmouse_leave_buffer_hook = intern ("mouse-leave-buffer-hook");
+  staticpro (&Qmouse_leave_buffer_hook);
+
   DEFVAR_LISP ("prefix-arg", &Vprefix_arg,
     "The value of the prefix argument for the next editing command.\n\
 It may be a number, or the symbol `-' for just a minus sign as arg,\n\
@@ -655,6 +680,20 @@ Bound each time `call-interactively' is called;\n\
 may be set by the debugger as a reminder for itself.");
   Vcommand_debug_status = Qnil;
 
+  DEFVAR_LISP ("mark-even-if-inactive", &Vmark_even_if_inactive,
+    "*Non-nil means you can use the mark even when inactive.\n\
+This option makes a difference in Transient Mark mode.\n\
+When the option is non-nil, deactivation of the mark\n\
+turns off region highlighting, but commands that use the mark\n\
+behave as if the mark were still active.");
+  Vmark_even_if_inactive = Qnil;
+
+  DEFVAR_LISP ("mouse-leave-buffer-hook", &Vmouse_leave_buffer_hook,
+    "Hook to run when about to switch windows with a mouse command.\n\
+Its purpose is to give temporary modes such as Isearch mode\n\
+a way to turn themselves off when a mouse command switches windows.");
+  Vmouse_leave_buffer_hook = Qnil;
+
   defsubr (&Sinteractive);
   defsubr (&Scall_interactively);
   defsubr (&Sprefix_numeric_value);