]> code.delx.au - gnu-emacs/blobdiff - src/callint.c
*** empty log message ***
[gnu-emacs] / src / callint.c
index 3b0d315db93d95a1704290f5b580786508882125..9dcc077fd658e61c288d4531d391de1f5a2a1187 100644 (file)
@@ -1,12 +1,12 @@
 /* Call a Lisp function interactively.
-   Copyright (C) 1985, 86, 93, 94, 95, 1997, 2000, 02, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 2000, 2001, 2002,
+                 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -16,8 +16,8 @@ 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., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 
 #include <config.h>
@@ -58,12 +58,9 @@ static Lisp_Object preserved_fns;
 /* Marker used within call-interactively to refer to point.  */
 static Lisp_Object point_marker;
 
-/* Buffer for the prompt text used in Fcall_interactively.  */
-static char *callint_message;
-
-/* Allocated length of that buffer.  */
-static int callint_message_size;
-
+/* String for the prompt text used in Fcall_interactively.  */
+static Lisp_Object callint_message;
+\f
 /* ARGSUSED */
 DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
        doc: /* Specify a way of parsing arguments for interactive use of a function.
@@ -98,18 +95,20 @@ e -- Parametrized event (i.e., one that's a list) that invoked this command.
      This skips events that are integers or symbols.
 f -- Existing file name.
 F -- Possibly nonexistent file name.
+G -- Possibly nonexistent file name, defaulting to just directory name.
 i -- Ignored, i.e. always nil.  Does not do I/O.
 k -- Key sequence (downcase the last event if needed to get a definition).
 K -- Key sequence to be redefined (do not downcase the last event).
 m -- Value of mark as number.  Does not do I/O.
 M -- Any string.  Inherits the current input method.
 n -- Number read using minibuffer.
-N -- Raw prefix arg, or if none, do like code `n'.
+N -- Numeric prefix arg, or if none, do like code `n'.
 p -- Prefix arg converted to number.  Does not do I/O.
 P -- Prefix arg in raw form.  Does not do I/O.
 r -- Region: point and mark as 2 numeric args, smallest first.  Does no I/O.
 s -- Any string.  Does not inherit the current input method.
 S -- Any symbol.
+U -- Mouse up event discarded by a previous k or K argument.
 v -- Variable name: symbol that is user-variable-p.
 x -- Lisp expression read but not evaluated.
 X -- Lisp expression read and evaluated.
@@ -172,7 +171,7 @@ check_mark (for_region)
           : "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);
+    xsignal0 (Qmark_inactive);
 }
 
 /* If the list of args INPUT was produced with an explicit call to
@@ -209,7 +208,7 @@ fix_command (input, values)
          Lisp_Object intail, valtail;
          for (intail = Fcdr (input), valtail = values;
               CONSP (valtail);
-              intail = Fcdr (intail), valtail = Fcdr (valtail))
+              intail = Fcdr (intail), valtail = XCDR (valtail))
            {
              Lisp_Object elt;
              elt = Fcar (intail);
@@ -255,18 +254,20 @@ See `interactive'.
 Optional second arg RECORD-FLAG non-nil
 means unconditionally put this command in the command-history.
 Otherwise, this is done only if an arg is read using the minibuffer.
+
 Optional third arg KEYS, if given, specifies the sequence of events to
-supply if the command inquires which events were used to invoke it.  */)
+supply, as a vector, if the command inquires which events were used to
+invoke it.  If KEYS is omitted or nil, the return value of
+`this-command-keys-vector' is used.  */)
      (function, record_flag, keys)
      Lisp_Object function, record_flag, keys;
 {
   Lisp_Object *args, *visargs;
-  unsigned char **argstrings;
   Lisp_Object fun;
-  Lisp_Object funcar;
   Lisp_Object specs;
   Lisp_Object filter_specs;
   Lisp_Object teml;
+  Lisp_Object up_event;
   Lisp_Object enable;
   int speccount = SPECPDL_INDEX ();
 
@@ -288,7 +289,7 @@ supply if the command inquires which events were used to invoke it.  */)
   char prompt1[100];
   char *tem1;
   int arg_from_tty = 0;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   int key_count;
   int record_then_fail = 0;
 
@@ -311,8 +312,6 @@ supply if the command inquires which events were used to invoke it.  */)
   /* Save this now, since use of minibuffer will clobber it. */
   prefix_arg = Vcurrent_prefix_arg;
 
- retry:
-
   if (SYMBOLP (function))
     enable = Fget (function, Qenable_recursive_minibuffers);
   else
@@ -327,9 +326,11 @@ supply if the command inquires which events were used to invoke it.  */)
      The feature is not fully implemented.  */
   filter_specs = Qnil;
 
+  /* 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 go to `retry'
-     to specify a different function, or set either STRING or SPECS.  */
+     or go to `lose' if not interactive, or set either STRING or SPECS.  */
 
   if (SUBRP (fun))
     {
@@ -337,8 +338,7 @@ supply if the command inquires which events were used to invoke it.  */)
       if (!string)
        {
        lose:
-         function = wrong_type_argument (Qcommandp, function);
-         goto retry;
+         wrong_type_argument (Qcommandp, function);
        }
     }
   else if (COMPILEDP (fun))
@@ -347,25 +347,17 @@ supply if the command inquires which events were used to invoke it.  */)
        goto lose;
       specs = XVECTOR (fun)->contents[COMPILED_INTERACTIVE];
     }
-  else if (!CONSP (fun))
-    goto lose;
-  else if (funcar = XCAR (fun), EQ (funcar, Qautoload))
+  else
     {
+      Lisp_Object form;
       GCPRO2 (function, prefix_arg);
-      do_autoload (fun, function);
+      form = Finteractive_form (function);
       UNGCPRO;
-      goto retry;
-    }
-  else if (EQ (funcar, Qlambda))
-    {
-      specs = Fassq (Qinteractive, Fcdr (XCDR (fun)));
-      if (NILP (specs))
+      if (CONSP (form))
+       specs = filter_specs = Fcar (XCDR (form));
+      else
        goto lose;
-      filter_specs = Fnth (make_number (1), specs);
-      specs = Fcar (Fcdr (specs));
     }
-  else
-    goto lose;
 
   /* If either SPECS or STRING is set to a string, use it.  */
   if (STRINGP (specs))
@@ -453,25 +445,25 @@ supply if the command inquires which events were used to invoke it.  */)
        string++;
       else if (*string == '@')
        {
-         Lisp_Object event;
+         Lisp_Object event, tem;
 
          event = (next_event < key_count
                   ? XVECTOR (keys)->contents[next_event]
                   : Qnil);
          if (EVENT_HAS_PARAMETERS (event)
-             && (event = XCDR (event), CONSP (event))
-             && (event = XCAR (event), CONSP (event))
-             && (event = XCAR (event), WINDOWP (event)))
+             && (tem = XCDR (event), CONSP (tem))
+             && (tem = XCAR (tem), CONSP (tem))
+             && (tem = XCAR (tem), WINDOWP (tem)))
            {
-             if (MINI_WINDOW_P (XWINDOW (event))
-                 && ! (minibuf_level > 0 && EQ (event, minibuf_window)))
+             if (MINI_WINDOW_P (XWINDOW (tem))
+                 && ! (minibuf_level > 0 && EQ (tem, 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, Qnil);
+             Fselect_window (tem, Qnil);
            }
          string++;
        }
@@ -496,7 +488,6 @@ supply if the command inquires which events were used to invoke it.  */)
 
   args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
   visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
-  argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *));
   varies = (int *) alloca ((count + 1) * sizeof (int));
 
   for (i = 0; i < (count + 1); i++)
@@ -506,7 +497,7 @@ supply if the command inquires which events were used to invoke it.  */)
       varies[i] = 0;
     }
 
-  GCPRO4 (prefix_arg, function, *args, *visargs);
+  GCPRO5 (prefix_arg, function, *args, *visargs, up_event);
   gcpro3.nvars = (count + 1);
   gcpro4.nvars = (count + 1);
 
@@ -520,34 +511,17 @@ supply if the command inquires which events were used to invoke it.  */)
       prompt1[sizeof prompt1 - 1] = 0;
       tem1 = (char *) index (prompt1, '\n');
       if (tem1) *tem1 = 0;
-      /* Fill argstrings with a vector of C strings
-        corresponding to the Lisp strings in visargs.  */
-      for (j = 1; j < i; j++)
-       argstrings[j]
-         = (EQ (visargs[j], Qnil)
-            ? (unsigned char *) ""
-            : SDATA (visargs[j]));
-
-      /* Process the format-string in prompt1, putting the output
-        into callint_message.  Make callint_message bigger if necessary.
-        We don't use a buffer on the stack, because the contents
-        need to stay stable for a while.  */
-      while (1)
-       {
-         int nchars = doprnt (callint_message, callint_message_size,
-                              prompt1, (char *)0,
-                              j - 1, (char **) argstrings + 1);
-         if (nchars < callint_message_size - 1)
-           break;
-         callint_message_size *= 2;
-         callint_message
-           = (char *) xrealloc (callint_message, callint_message_size);
-       }
+
+      visargs[0] = build_string (prompt1);
+      if (index (prompt1, '%'))
+       callint_message = Fformat (i, visargs);
+      else
+       callint_message = visargs[0];
 
       switch (*tem)
        {
        case 'a':               /* Symbol defined as a function */
-         visargs[i] = Fcompleting_read (build_string (callint_message),
+         visargs[i] = Fcompleting_read (callint_message,
                                         Vobarray, Qfboundp, Qt,
                                         Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
@@ -559,17 +533,17 @@ supply if the command inquires which events were used to invoke it.  */)
          args[i] = Fcurrent_buffer ();
          if (EQ (selected_window, minibuf_window))
            args[i] = Fother_buffer (args[i], Qnil, Qnil);
-         args[i] = Fread_buffer (build_string (callint_message), args[i], Qt);
+         args[i] = Fread_buffer (callint_message, args[i], Qt);
          break;
 
        case 'B':               /* Name of buffer, possibly nonexistent */
-         args[i] = Fread_buffer (build_string (callint_message),
+         args[i] = Fread_buffer (callint_message,
                                  Fother_buffer (Fcurrent_buffer (), Qnil, Qnil),
                                  Qnil);
          break;
 
         case 'c':              /* Character */
-         args[i] = Fread_char (build_string (callint_message), Qnil);
+         args[i] = Fread_char (callint_message, Qnil, Qnil);
          message1_nolog ((char *) 0);
          /* Passing args[i] directly stimulates compiler bug */
          teml = args[i];
@@ -577,7 +551,7 @@ supply if the command inquires which events were used to invoke it.  */)
          break;
 
        case 'C':               /* Command: symbol with interactive function */
-         visargs[i] = Fcompleting_read (build_string (callint_message),
+         visargs[i] = Fcompleting_read (callint_message,
                                         Vobarray, Qcommandp,
                                         Qt, Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
@@ -593,21 +567,27 @@ supply if the command inquires which events were used to invoke it.  */)
          break;
 
        case 'D':               /* Directory name. */
-         args[i] = Fread_file_name (build_string (callint_message), Qnil,
+         args[i] = Fread_file_name (callint_message, Qnil,
                                     current_buffer->directory, Qlambda, Qnil,
                                     Qfile_directory_p);
          break;
 
        case 'f':               /* Existing file name. */
-         args[i] = Fread_file_name (build_string (callint_message),
+         args[i] = Fread_file_name (callint_message,
                                     Qnil, Qnil, Qlambda, Qnil, Qnil);
          break;
 
        case 'F':               /* Possibly nonexistent file name. */
-         args[i] = Fread_file_name (build_string (callint_message),
+         args[i] = Fread_file_name (callint_message,
                                     Qnil, Qnil, Qnil, Qnil, Qnil);
          break;
 
+       case 'G':               /* Possibly nonexistent file name,
+                                  default to directory alone. */
+         args[i] = Fread_file_name (callint_message,
+                                    Qnil, Qnil, Qnil, build_string (""), Qnil);
+         break;
+
        case 'i':               /* Ignore an argument -- Does not do I/O */
          varies[i] = -1;
          break;
@@ -616,11 +596,11 @@ supply if the command inquires which events were used to invoke it.  */)
          {
            int speccount1 = SPECPDL_INDEX ();
            specbind (Qcursor_in_echo_area, Qt);
-           args[i] = Fread_key_sequence (build_string (callint_message),
+           args[i] = Fread_key_sequence (callint_message,
                                          Qnil, Qnil, Qnil, Qnil);
            unbind_to (speccount1, Qnil);
            teml = args[i];
-           visargs[i] = Fkey_description (teml);
+           visargs[i] = Fkey_description (teml, Qnil);
 
            /* If the key sequence ends with a down-event,
               discard the following up-event.  */
@@ -635,7 +615,7 @@ supply if the command inquires which events were used to invoke it.  */)
                /* Ignore first element, which is the base key.  */
                tem2 = Fmemq (intern ("down"), Fcdr (teml));
                if (! NILP (tem2))
-                 Fread_event (Qnil, Qnil);
+                 up_event = Fread_event (Qnil, Qnil, Qnil);
              }
          }
          break;
@@ -644,10 +624,10 @@ supply if the command inquires which events were used to invoke it.  */)
          {
            int speccount1 = SPECPDL_INDEX ();
            specbind (Qcursor_in_echo_area, Qt);
-           args[i] = Fread_key_sequence (build_string (callint_message),
+           args[i] = Fread_key_sequence (callint_message,
                                          Qnil, Qt, Qnil, Qnil);
            teml = args[i];
-           visargs[i] = Fkey_description (teml);
+           visargs[i] = Fkey_description (teml, Qnil);
            unbind_to (speccount1, Qnil);
 
            /* If the key sequence ends with a down-event,
@@ -663,11 +643,21 @@ supply if the command inquires which events were used to invoke it.  */)
                /* Ignore first element, which is the base key.  */
                tem2 = Fmemq (intern ("down"), Fcdr (teml));
                if (! NILP (tem2))
-                 Fread_event (Qnil, Qnil);
+                 up_event = Fread_event (Qnil, Qnil, Qnil);
              }
          }
          break;
 
+       case 'U':               /* Up event from last k or K */
+         if (!NILP (up_event))
+           {
+             args[i] = Fmake_vector (make_number (1), up_event);
+             up_event = Qnil;
+             teml = args[i];
+             visargs[i] = Fkey_description (teml, Qnil);
+           }
+         break;
+
        case 'e':               /* The invoking event.  */
          if (next_event >= key_count)
            error ("%s must be bound to an event with parameters",
@@ -694,11 +684,11 @@ supply if the command inquires which events were used to invoke it.  */)
 
        case 'M':               /* String read via minibuffer with
                                   inheriting the current input method.  */
-         args[i] = Fread_string (build_string (callint_message),
+         args[i] = Fread_string (callint_message,
                                  Qnil, Qnil, Qnil, Qt);
          break;
 
-       case 'N':               /* Prefix arg, else number from minibuffer */
+       case 'N':               /* Prefix arg as number, else number from minibuffer */
          if (!NILP (prefix_arg))
            goto have_prefix_arg;
        case 'n':               /* Read number from minibuffer.  */
@@ -707,14 +697,14 @@ supply if the command inquires which events were used to invoke it.  */)
            do
              {
                Lisp_Object tem;
-               if (!  first)
+               if (! first)
                  {
                    message ("Please enter a number.");
-                   sit_for (1, 0, 0, 0, 0);
+                   sit_for (make_number (1), 0, 0);
                  }
                first = 0;
 
-               tem = Fread_from_minibuffer (build_string (callint_message),
+               tem = Fread_from_minibuffer (callint_message,
                                             Qnil, Qnil, Qnil, Qnil, Qnil,
                                             Qnil);
                if (! STRINGP (tem) || SCHARS (tem) == 0)
@@ -724,7 +714,7 @@ supply if the command inquires which events were used to invoke it.  */)
              }
            while (! NUMBERP (args[i]));
          }
-         visargs[i] = last_minibuf_string;
+         visargs[i] = args[i];
          break;
 
        case 'P':               /* Prefix arg in raw form.  Does no I/O.  */
@@ -754,12 +744,12 @@ supply if the command inquires which events were used to invoke it.  */)
 
        case 's':               /* String read via minibuffer without
                                   inheriting the current input method.  */
-         args[i] = Fread_string (build_string (callint_message),
+         args[i] = Fread_string (callint_message,
                                  Qnil, Qnil, Qnil, Qnil);
          break;
 
        case 'S':               /* Any symbol.  */
-         visargs[i] = Fread_string (build_string (callint_message),
+         visargs[i] = Fread_string (callint_message,
                                     Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
          teml = visargs[i];
@@ -768,17 +758,17 @@ supply if the command inquires which events were used to invoke it.  */)
 
        case 'v':               /* Variable name: symbol that is
                                   user-variable-p. */
-         args[i] = Fread_variable (build_string (callint_message), Qnil);
+         args[i] = Fread_variable (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
 
        case 'x':               /* Lisp expression read but not evaluated */
-         args[i] = Fread_minibuffer (build_string (callint_message), Qnil);
+         args[i] = Fread_minibuffer (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
 
        case 'X':               /* Lisp expression read and evaluated */
-         args[i] = Feval_minibuffer (build_string (callint_message), Qnil);
+         args[i] = Feval_minibuffer (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
 
@@ -792,13 +782,13 @@ supply if the command inquires which events were used to invoke it.  */)
          else
            {
              args[i]
-               = Fread_non_nil_coding_system (build_string (callint_message));
+               = Fread_non_nil_coding_system (callint_message);
              visargs[i] = last_minibuf_string;
            }
          break;
 
        case 'z':               /* Coding-system symbol or nil */
-         args[i] = Fread_coding_system (build_string (callint_message), Qnil);
+         args[i] = Fread_coding_system (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
 
@@ -903,6 +893,9 @@ syms_of_callint ()
   point_marker = Fmake_marker ();
   staticpro (&point_marker);
 
+  callint_message = Qnil;
+  staticpro (&callint_message);
+
   preserved_fns = Fcons (intern ("region-beginning"),
                         Fcons (intern ("region-end"),
                                Fcons (intern ("point"),
@@ -942,10 +935,6 @@ syms_of_callint ()
   Qmouse_leave_buffer_hook = intern ("mouse-leave-buffer-hook");
   staticpro (&Qmouse_leave_buffer_hook);
 
-  callint_message_size = 100;
-  callint_message = (char *) xmalloc (callint_message_size);
-
-
   DEFVAR_KBOARD ("prefix-arg", Vprefix_arg,
                 doc: /* The value of the prefix argument for the next editing command.
 It may be a number, or the symbol `-' for just a minus sign as arg,
@@ -998,3 +987,6 @@ a way to turn themselves off when a mouse command switches windows.  */);
   defsubr (&Scall_interactively);
   defsubr (&Sprefix_numeric_value);
 }
+
+/* arch-tag: a3a7cad7-bcac-42ce-916e-1bd2546ebf37
+   (do not change this comment) */