(cl-macroexpand-all): Declare.
[bpt/emacs.git] / src / callint.c
index 887f876..467790c 100644 (file)
@@ -1,13 +1,14 @@
 /* Call a Lisp function interactively.
    Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 2000, 2001, 2002,
-                 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+                 2003, 2004, 2005, 2006, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #include <config.h>
@@ -35,6 +34,7 @@ extern char *index P_ ((const char *, int));
 
 extern Lisp_Object Qcursor_in_echo_area;
 extern Lisp_Object Qfile_directory_p;
+extern Lisp_Object Qonly;
 
 Lisp_Object Vcurrent_prefix_arg, Qminus, Qplus;
 Lisp_Object Qcall_interactively;
@@ -50,6 +50,8 @@ Lisp_Object Qenable_recursive_minibuffers;
    even if mark_active is 0.  */
 Lisp_Object Vmark_even_if_inactive;
 
+Lisp_Object Vshift_select_mode, Qhandle_shift_selection;
+
 Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook;
 
 Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion, Qprogn, Qif, Qwhen;
@@ -114,14 +116,16 @@ x -- Lisp expression read but not evaluated.
 X -- Lisp expression read and evaluated.
 z -- Coding system.
 Z -- Coding system, nil if no prefix arg.
-In addition, if the string begins with `*'
- then an error is signaled if the buffer is read-only.
- This happens before reading any arguments.
-If the string begins with `@', then Emacs searches the key sequence
- which invoked the command for its first mouse click (or any other
- event which specifies a window), and selects that window before
- reading any arguments.  You may use both `@' and `*'; they are
- processed in the order that they appear.
+
+In addition, if the string begins with `*', an error is signaled if
+  the buffer is read-only.
+If the string begins with `@', Emacs searches the key sequence which
+ invoked the command for its first mouse click (or any other event
+ which specifies a window).
+If the string begins with `^' and `shift-select-mode' is non-nil,
+ Emacs first calls the function `handle-shift-select'.
+You may use `@', `*', and `^' together.  They are processed in the
+ order that they appear, before reading any arguments.
 usage: (interactive ARGS)  */)
      (args)
      Lisp_Object args;
@@ -263,7 +267,6 @@ invoke it.  If KEYS is omitted or nil, the return value of
      Lisp_Object function, record_flag, keys;
 {
   Lisp_Object *args, *visargs;
-  Lisp_Object fun;
   Lisp_Object specs;
   Lisp_Object filter_specs;
   Lisp_Object teml;
@@ -317,8 +320,6 @@ invoke it.  If KEYS is omitted or nil, the return value of
   else
     enable = Qnil;
 
-  fun = indirect_function (function);
-
   specs = Qnil;
   string = 0;
   /* The idea of FILTER_SPECS is to provide away to
@@ -329,37 +330,19 @@ invoke it.  If KEYS is omitted or nil, the return value of
   /* If k or K discard an up-event, save it here so it can be retrieved with U */
   up_event = Qnil;
 
-  /* Decode the kind of function.  Either handle it and return,
-     or go to `lose' if not interactive, or set either STRING or SPECS.  */
-
-  if (SUBRP (fun))
-    {
-      string = (unsigned char *) XSUBR (fun)->prompt;
-      if (!string)
-       {
-       lose:
-         wrong_type_argument (Qcommandp, function);
-       }
-    }
-  else if (COMPILEDP (fun))
-    {
-      if ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_INTERACTIVE)
-       goto lose;
-      specs = XVECTOR (fun)->contents[COMPILED_INTERACTIVE];
-    }
-  else
-    {
-      Lisp_Object form;
-      GCPRO2 (function, prefix_arg);
-      form = Finteractive_form (function);
-      UNGCPRO;
-      if (CONSP (form))
-       specs = filter_specs = Fcar (XCDR (form));
-      else
-       goto lose;
-    }
+  /* Set SPECS to the interactive form, or barf if not interactive.  */
+  {
+    Lisp_Object form;
+    GCPRO2 (function, prefix_arg);
+    form = Finteractive_form (function);
+    UNGCPRO;
+    if (CONSP (form))
+      specs = filter_specs = Fcar (XCDR (form));
+    else
+      wrong_type_argument (Qcommandp, function);
+  }
 
-  /* If either SPECS or STRING is set to a string, use it.  */
+  /* If SPECS is set to a string, use it as an interactive prompt.  */
   if (STRINGP (specs))
     {
       /* Make a copy of string so that if a GC relocates specs,
@@ -368,7 +351,7 @@ invoke it.  If KEYS is omitted or nil, the return value of
       bcopy (SDATA (specs), string,
             SBYTES (specs) + 1);
     }
-  else if (string == 0)
+  else
     {
       Lisp_Object input;
       i = num_input_events;
@@ -402,15 +385,15 @@ invoke it.  If KEYS is omitted or nil, the return value of
       real_this_command= save_real_this_command;
       current_kboard->Vlast_command = save_last_command;
 
-      single_kboard_state ();
-      return apply1 (function, specs);
+      temporarily_switch_to_single_kboard (NULL);
+      return unbind_to (speccount, apply1 (function, specs));
     }
 
   /* Here if function specifies a string to control parsing the defaults */
 
   /* Set next_event to point to the first event with parameters.  */
   for (next_event = 0; next_event < key_count; next_event++)
-    if (EVENT_HAS_PARAMETERS (XVECTOR (keys)->contents[next_event]))
+    if (EVENT_HAS_PARAMETERS (AREF (keys, next_event)))
       break;
 
   /* Handle special starting chars `*' and `@'.  Also `-'.  */
@@ -448,7 +431,7 @@ invoke it.  If KEYS is omitted or nil, the return value of
          Lisp_Object event, tem;
 
          event = (next_event < key_count
-                  ? XVECTOR (keys)->contents[next_event]
+                  ? AREF (keys, next_event)
                   : Qnil);
          if (EVENT_HAS_PARAMETERS (event)
              && (tem = XCDR (event), CONSP (tem))
@@ -467,6 +450,18 @@ invoke it.  If KEYS is omitted or nil, the return value of
            }
          string++;
        }
+      else if (*string == '^')
+       {
+         if (! NILP (Vshift_select_mode))
+           call1 (Qhandle_shift_selection, Qnil);
+         /* Even if shift-select-mode is off, temporarily active
+            regions could be set using the mouse, and should be
+            deactivated.  */
+         else if (CONSP (Vtransient_mark_mode)
+                  && EQ (XCAR (Vtransient_mark_mode), Qonly))
+           call1 (Qhandle_shift_selection, Qt);
+         string++;
+       }
       else break;
     }
 
@@ -667,13 +662,13 @@ invoke it.  If KEYS is omitted or nil, the return value of
                   (SYMBOLP (function)
                    ? (char *) SDATA (SYMBOL_NAME (function))
                    : "command"));
-         args[i] = XVECTOR (keys)->contents[next_event++];
+         args[i] = AREF (keys, next_event);
+         next_event++;
          varies[i] = -1;
 
          /* Find the next parameterized event.  */
          while (next_event < key_count
-                && ! (EVENT_HAS_PARAMETERS
-                      (XVECTOR (keys)->contents[next_event])))
+                && !(EVENT_HAS_PARAMETERS (AREF (keys, next_event))))
            next_event++;
 
          break;
@@ -854,12 +849,11 @@ invoke it.  If KEYS is omitted or nil, the return value of
   real_this_command= save_real_this_command;
   current_kboard->Vlast_command = save_last_command;
 
-  single_kboard_state ();
-
   {
     Lisp_Object val;
     specbind (Qcommand_debug_status, Qnil);
 
+    temporarily_switch_to_single_kboard (NULL);
     val = Ffuncall (count + 1, args);
     UNGCPRO;
     return unbind_to (speccount, val);
@@ -926,6 +920,9 @@ syms_of_callint ()
   Qplus = intern ("+");
   staticpro (&Qplus);
 
+  Qhandle_shift_selection = intern ("handle-shift-selection");
+  staticpro (&Qhandle_shift_selection);
+
   Qcall_interactively = intern ("call-interactively");
   staticpro (&Qcall_interactively);
 
@@ -963,7 +960,10 @@ This is what `(interactive \"P\")' returns.  */);
 
   DEFVAR_LISP ("command-history", &Vcommand_history,
               doc: /* List of recent commands that read arguments from terminal.
-Each command is represented as a form to evaluate.  */);
+Each command is represented as a form to evaluate.
+
+Maximum length of the history list is determined by the value
+of `history-length', which see.  */);
   Vcommand_history = Qnil;
 
   DEFVAR_LISP ("command-debug-status", &Vcommand_debug_status,
@@ -978,7 +978,21 @@ This option makes a difference in Transient Mark mode.
 When the option is non-nil, deactivation of the mark
 turns off region highlighting, but commands that use the mark
 behave as if the mark were still active.  */);
-  Vmark_even_if_inactive = Qnil;
+  Vmark_even_if_inactive = Qt;
+
+  DEFVAR_LISP ("shift-select-mode", &Vshift_select_mode,
+              doc: /* When non-nil, shifted motion keys activate the mark momentarily.
+
+While the mark is activated in this way, any shift-translated point
+motion key extends the region, and if Transient Mark mode was off, it
+is temporarily turned on.  Furthermore, the mark will be deactivated
+by any subsequent point motion key that was not shift-translated, or
+by any action that normally deactivates the mark in Transient Mark
+mode.
+
+See `this-command-keys-shift-translated' for the meaning of
+shift-translation.  */);
+  Vshift_select_mode = Qt;
 
   DEFVAR_LISP ("mouse-leave-buffer-hook", &Vmouse_leave_buffer_hook,
               doc: /* Hook to run when about to switch windows with a mouse command.