(check_x_display_info, check_x_frame, x_set_font)
[bpt/emacs.git] / src / callint.c
index cb49ec0..a509dc4 100644 (file)
@@ -41,12 +41,17 @@ Lisp_Object Vmark_even_if_inactive;
 
 Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook;
 
-Lisp_Object Qlist;
+Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion;
 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;
 
 /* This comment supplies the doc string for interactive,
    for make-docfile to see.  We cannot put this in the real DEFUN
@@ -159,8 +164,9 @@ check_mark ()
 }
 
 
-DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 2, 0,
+DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0,
   "Call FUNCTION, reading args according to its interactive calling specs.\n\
+Return the value FUNCTION returns.\n\
 The function contains a specification of how to do the argument reading.\n\
 In the case of user-defined functions, this is specified by placing a call\n\
 to the function `interactive' at the top level of the function body.\n\
@@ -169,8 +175,8 @@ See `interactive'.\n\
 Optional second arg RECORD-FLAG non-nil\n\
 means unconditionally put this command in the command-history.\n\
 Otherwise, this is done only if an arg is read using the minibuffer.")
-  (function, record)
-     Lisp_Object function, record;
+  (function, record, keys)
+     Lisp_Object function, record, keys;
 {
   Lisp_Object *args, *visargs;
   unsigned char **argstrings;
@@ -196,11 +202,19 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
 
   register int i, j;
   int count, foo;
-  char prompt[100];
   char prompt1[100];
   char *tem1;
   int arg_from_tty = 0;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  int key_count;
+
+  if (NILP (keys))
+    keys = this_command_keys, key_count = this_command_key_count;
+  else
+    {
+      CHECK_VECTOR (keys, 3);
+      key_count = XVECTOR (keys)->size;
+    }
 
   /* Save this now, since use of minibuffer will clobber it. */
   prefix_arg = Vcurrent_prefix_arg;
@@ -288,22 +302,36 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
             look for elements that were computed with (region-beginning)
             or (region-end), and put those expressions into VALUES
             instead of the present values.  */
-         car = Fcar (input);
-         if (EQ (car, Qlist))
+         if (CONSP (input))
            {
-             Lisp_Object intail, valtail;
-             for (intail = Fcdr (input), valtail = values;
-                  CONSP (valtail);
-                  intail = Fcdr (intail), valtail = Fcdr (valtail))
+             car = XCONS (input)->car;
+             /* Skip through certain special forms.  */
+             while (EQ (car, Qlet) || EQ (car, Qletx)
+                    || EQ (car, Qsave_excursion))
+               {
+                 while (CONSP (XCONS (input)->cdr))
+                   input = XCONS (input)->cdr;
+                 input = XCONS (input)->car;
+                 if (!CONSP (input))
+                   break;
+                 car = XCONS (input)->car;
+               }
+             if (EQ (car, Qlist))
                {
-                 Lisp_Object elt;
-                 elt = Fcar (intail);
-                 if (CONSP (elt))
+                 Lisp_Object intail, valtail;
+                 for (intail = Fcdr (input), valtail = values;
+                      CONSP (valtail);
+                      intail = Fcdr (intail), valtail = Fcdr (valtail))
                    {
-                     Lisp_Object presflag;
-                     presflag = Fmemq (Fcar (elt), preserved_fns);
-                     if (!NILP (presflag))
-                       Fsetcar (valtail, Fcar (intail));
+                     Lisp_Object elt;
+                     elt = Fcar (intail);
+                     if (CONSP (elt))
+                       {
+                         Lisp_Object presflag;
+                         presflag = Fmemq (Fcar (elt), preserved_fns);
+                         if (!NILP (presflag))
+                           Fsetcar (valtail, Fcar (intail));
+                       }
                    }
                }
            }
@@ -317,9 +345,8 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
   /* 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 < this_command_key_count; next_event++)
-    if (EVENT_HAS_PARAMETERS
-       (XVECTOR (this_command_keys)->contents[next_event]))
+  for (next_event = 0; next_event < key_count; next_event++)
+    if (EVENT_HAS_PARAMETERS (XVECTOR (keys)->contents[next_event]))
       break;
   
   /* Handle special starting chars `*' and `@'.  Also `-'.  */
@@ -341,7 +368,7 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
        {
          Lisp_Object event;
 
-         event = XVECTOR (this_command_keys)->contents[next_event];
+         event = XVECTOR (keys)->contents[next_event];
          if (EVENT_HAS_PARAMETERS (event)
              && (event = XCONS (event)->cdr, CONSP (event))
              && (event = XCONS (event)->car, CONSP (event))
@@ -412,13 +439,26 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
            ? (unsigned char *) ""
              : XSTRING (visargs[j])->data;
 
-      doprnt (prompt, sizeof prompt, prompt1, (char *)0,
-             j - 1, argstrings + 1);
+      /* 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, argstrings + 1);
+         if (nchars < callint_message_size)
+           break;
+         callint_message_size *= 2;
+         callint_message
+           = (char *) xrealloc (callint_message, callint_message_size);
+       }
 
       switch (*tem)
        {
        case 'a':               /* Symbol defined as a function */
-         visargs[i] = Fcompleting_read (build_string (prompt),
+         visargs[i] = Fcompleting_read (build_string (callint_message),
                                         Vobarray, Qfboundp, Qt, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
          teml = visargs[i];
@@ -429,25 +469,26 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
          args[i] = Fcurrent_buffer ();
          if (EQ (selected_window, minibuf_window))
            args[i] = Fother_buffer (args[i], Qnil);
-         args[i] = Fread_buffer (build_string (prompt), args[i], Qt);
+         args[i] = Fread_buffer (build_string (callint_message), args[i], Qt);
          break;
 
        case 'B':               /* Name of buffer, possibly nonexistent */
-         args[i] = Fread_buffer (build_string (prompt),
+         args[i] = Fread_buffer (build_string (callint_message),
                                  Fother_buffer (Fcurrent_buffer (), Qnil),
                                  Qnil);
          break;
 
         case 'c':              /* Character */
-         message1 (prompt);
+         message1_nolog (callint_message);
          args[i] = Fread_char ();
+         message1_nolog ((char *) 0);
          /* Passing args[i] directly stimulates compiler bug */
          teml = args[i];
          visargs[i] = Fchar_to_string (teml);
          break;
 
        case 'C':               /* Command: symbol with interactive function */
-         visargs[i] = Fcompleting_read (build_string (prompt),
+         visargs[i] = Fcompleting_read (build_string (callint_message),
                                         Vobarray, Qcommandp, Qt, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
          teml = visargs[i];
@@ -462,45 +503,47 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
          break;
 
        case 'D':               /* Directory name. */
-         args[i] = Fread_file_name (build_string (prompt), Qnil,
+         args[i] = Fread_file_name (build_string (callint_message), Qnil,
                                     current_buffer->directory, Qlambda, Qnil);
          break;
 
        case 'f':               /* Existing file name. */
-         args[i] = Fread_file_name (build_string (prompt),
+         args[i] = Fread_file_name (build_string (callint_message),
                                     Qnil, Qnil, Qlambda, Qnil);
          break;
 
        case 'F':               /* Possibly nonexistent file name. */
-         args[i] = Fread_file_name (build_string (prompt),
+         args[i] = Fread_file_name (build_string (callint_message),
                                     Qnil, Qnil, Qnil, Qnil);
          break;
 
        case 'k':               /* Key sequence. */
-         args[i] = Fread_key_sequence (build_string (prompt), Qnil, Qnil, Qnil);
+         args[i] = Fread_key_sequence (build_string (callint_message),
+                                       Qnil, Qnil, Qnil);
          teml = args[i];
          visargs[i] = Fkey_description (teml);
          break;
 
        case 'K':               /* Key sequence to be defined. */
-         args[i] = Fread_key_sequence (build_string (prompt), Qnil, Qt, Qnil);
+         args[i] = Fread_key_sequence (build_string (callint_message),
+                                       Qnil, Qt, Qnil);
          teml = args[i];
          visargs[i] = Fkey_description (teml);
          break;
 
        case 'e':               /* The invoking event.  */
-         if (next_event >= this_command_key_count)
+         if (next_event >= key_count)
            error ("%s must be bound to an event with parameters",
                   (SYMBOLP (function)
                    ? (char *) XSYMBOL (function)->name->data
                    : "command"));
-         args[i] = XVECTOR (this_command_keys)->contents[next_event++];
+         args[i] = XVECTOR (keys)->contents[next_event++];
          varies[i] = -1;
 
          /* Find the next parameterized event.  */
-         while (next_event < this_command_key_count
+         while (next_event < key_count
                 && ! (EVENT_HAS_PARAMETERS
-                      (XVECTOR (this_command_keys)->contents[next_event])))
+                      (XVECTOR (keys)->contents[next_event])))
            next_event++;
 
          break;
@@ -517,19 +560,19 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
            goto have_prefix_arg;
        case 'n':               /* Read number from minibuffer.  */
          do
-           args[i] = Fread_minibuffer (build_string (prompt), Qnil);
+           args[i] = Fread_minibuffer (build_string (callint_message), Qnil);
          while (! NUMBERP (args[i]));
          visargs[i] = last_minibuf_string;
          break;
 
        case 'P':               /* Prefix arg in raw form.  Does no I/O.  */
-       have_prefix_arg:
          args[i] = prefix_arg;
          /* visargs[i] = Qnil; */
          varies[i] = -1;
          break;
 
        case 'p':               /* Prefix arg converted to number.  No I/O. */
+       have_prefix_arg:
          args[i] = Fprefix_numeric_value (prefix_arg);
          /* visargs[i] = Qnil; */
          varies[i] = -1;
@@ -548,11 +591,12 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
          break;
 
        case 's':               /* String read via minibuffer.  */
-         args[i] = Fread_string (build_string (prompt), Qnil, Qnil);
+         args[i] = Fread_string (build_string (callint_message), Qnil, Qnil);
          break;
 
        case 'S':               /* Any symbol.  */
-         visargs[i] = Fread_string (build_string (prompt), Qnil, Qnil);
+         visargs[i] = Fread_string (build_string (callint_message),
+                                    Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
          teml = visargs[i];
          args[i] = Fintern (teml, Qnil);
@@ -560,17 +604,17 @@ Otherwise, this is done only if an arg is read using the minibuffer.")
 
        case 'v':               /* Variable name: symbol that is
                                   user-variable-p. */
-         args[i] = Fread_variable (build_string (prompt));
+         args[i] = Fread_variable (build_string (callint_message));
          visargs[i] = last_minibuf_string;
          break;
 
        case 'x':               /* Lisp expression read but not evaluated */
-         args[i] = Fread_minibuffer (build_string (prompt), Qnil);
+         args[i] = Fread_minibuffer (build_string (callint_message), Qnil);
          visargs[i] = last_minibuf_string;
          break;
 
        case 'X':               /* Lisp expression read and evaluated */
-         args[i] = Feval_minibuffer (build_string (prompt), Qnil);
+         args[i] = Feval_minibuffer (build_string (callint_message), Qnil);
          visargs[i] = last_minibuf_string;
          break;
 
@@ -644,7 +688,7 @@ Its numeric meaning is what you would get from `(interactive \"p\")'.")
     XSETFASTINT (val, 1);
   else if (EQ (raw, Qminus))
     XSETINT (val, -1);
-  else if (CONSP (raw))
+  else if (CONSP (raw) && INTEGERP (XCONS (raw)->car))
     XSETINT (val, XINT (XCONS (raw)->car));
   else if (INTEGERP (raw))
     val = raw;
@@ -667,6 +711,12 @@ syms_of_callint ()
 
   Qlist = intern ("list");
   staticpro (&Qlist);
+  Qlet = intern ("let");
+  staticpro (&Qlet);
+  Qletx = intern ("let*");
+  staticpro (&Qletx);
+  Qsave_excursion = intern ("save-excursion");
+  staticpro (&Qsave_excursion);
 
   Qminus = intern ("-");
   staticpro (&Qminus);
@@ -686,6 +736,10 @@ 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,
     "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\