use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / minibuf.c
index d921e80..e257ac2 100644 (file)
@@ -1,6 +1,6 @@
 /* Minibuffer input and completion.
 
-Copyright (C) 1985-1986, 1993-201 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 1993-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -21,10 +21,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <errno.h>
 #include <stdio.h>
-#include <setjmp.h>
 
 #include "lisp.h"
 #include "commands.h"
+#include "character.h"
 #include "buffer.h"
 #include "dispextern.h"
 #include "keyboard.h"
@@ -109,14 +109,16 @@ choose_minibuf_frame (void)
       /* I don't think that any frames may validly have a null minibuffer
         window anymore.  */
       if (NILP (sf->minibuffer_window))
-       abort ();
+       emacs_abort ();
 
       /* Under X, we come here with minibuf_window being the
         minibuffer window of the unused termcap window created in
         init_window_once.  That window doesn't have a buffer.  */
-      buffer = XWINDOW (minibuf_window)->buffer;
+      buffer = XWINDOW (minibuf_window)->contents;
       if (BUFFERP (buffer))
-       Fset_window_buffer (sf->minibuffer_window, buffer, Qnil);
+       /* Use set_window_buffer instead of Fset_window_buffer (see
+          discussion of bug#11984, bug#12025, bug#12026).  */
+       set_window_buffer (sf->minibuffer_window, buffer, 0, 0);
       minibuf_window = sf->minibuffer_window;
     }
 
@@ -135,13 +137,6 @@ choose_minibuf_frame (void)
   }
 }
 
-static Lisp_Object
-choose_minibuf_frame_1 (Lisp_Object ignore)
-{
-  choose_minibuf_frame ();
-  return Qnil;
-}
-
 DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
        Sactive_minibuffer_window, 0, 0, 0,
        doc: /* Return the currently active minibuffer window, or nil if none.  */)
@@ -169,19 +164,8 @@ without invoking the usual minibuffer commands.  */)
 \f
 /* Actual minibuffer invocation.  */
 
-static Lisp_Object read_minibuf_unwind (Lisp_Object);
-static Lisp_Object run_exit_minibuf_hook (Lisp_Object);
-static Lisp_Object read_minibuf (Lisp_Object, Lisp_Object,
-                                 Lisp_Object,
-                                 int, Lisp_Object,
-                                 Lisp_Object, Lisp_Object,
-                                 int, int);
-static Lisp_Object read_minibuf_noninteractive (Lisp_Object, Lisp_Object,
-                                                Lisp_Object, Lisp_Object,
-                                                int, Lisp_Object,
-                                                Lisp_Object, Lisp_Object,
-                                                int, int);
-static Lisp_Object string_to_object (Lisp_Object, Lisp_Object);
+static void read_minibuf_unwind (void);
+static void run_exit_minibuf_hook (void);
 
 
 /* Read a Lisp object from VAL and return it.  If VAL is an empty
@@ -221,7 +205,7 @@ string_to_object (Lisp_Object val, Lisp_Object defalt)
     }
 
   val = Fcar (expr_and_pos);
-  RETURN_UNGCPRO (val);
+  return val;
 }
 
 
@@ -231,10 +215,10 @@ string_to_object (Lisp_Object val, Lisp_Object defalt)
 static Lisp_Object
 read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
                             Lisp_Object prompt, Lisp_Object backup_n,
-                            int expflag,
+                            bool expflag,
                             Lisp_Object histvar, Lisp_Object histpos,
                             Lisp_Object defalt,
-                            int allow_props, int inherit_input_method)
+                            bool allow_props, bool inherit_input_method)
 {
   ptrdiff_t size, len;
   char *line;
@@ -247,7 +231,7 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
   val = Qnil;
   size = 100;
   len = 0;
-  line = (char *) xmalloc (size);
+  line = xmalloc_atomic (size);
 
   while ((c = getchar ()) != '\n')
     {
@@ -263,7 +247,7 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
              if (STRING_BYTES_BOUND / 2 < size)
                memory_full (SIZE_MAX);
              size *= 2;
-             line = (char *) xrealloc (line, size);
+             line = xrealloc (line, size);
            }
          line[len++] = c;
        }
@@ -374,43 +358,46 @@ If the current buffer is not a minibuffer, return its entire contents.  */)
    beginning of INITIAL if N <= 0.
 
    Normally return the result as a string (the text that was read),
-   but if EXPFLAG is nonzero, read it and return the object read.
+   but if EXPFLAG, read it and return the object read.
    If HISTVAR is given, save the value read on that history only if it doesn't
    match the front of that history list exactly.  The value is pushed onto
    the list as the string that was read.
 
    DEFALT specifies the default value for the sake of history commands.
 
-   If ALLOW_PROPS is nonzero, we do not throw away text properties.
+   If ALLOW_PROPS, do not throw away text properties.
 
-   if INHERIT_INPUT_METHOD is nonzero, the minibuffer inherits the
+   if INHERIT_INPUT_METHOD, the minibuffer inherits the
    current input method.  */
 
 static Lisp_Object
 read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
-             int expflag,
+             bool expflag,
              Lisp_Object histvar, Lisp_Object histpos, Lisp_Object defalt,
-             int allow_props, int inherit_input_method)
+             bool allow_props, bool inherit_input_method)
 {
   Lisp_Object val;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
   Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   Lisp_Object enable_multibyte;
   EMACS_INT pos = 0;
   /* String to add to the history.  */
   Lisp_Object histstring;
+  Lisp_Object histval;
 
   Lisp_Object empty_minibuf;
   Lisp_Object dummy, frame;
 
   specbind (Qminibuffer_default, defalt);
+  specbind (intern ("inhibit-read-only"), Qnil);
 
   /* If Vminibuffer_completing_file_name is `lambda' on entry, it was t
      in previous recursive minibuffer, but was not set explicitly
      to t for this invocation, so set it to nil in this minibuffer.
      Save the old value now, before we change it.  */
-  specbind (intern ("minibuffer-completing-file-name"), Vminibuffer_completing_file_name);
+  specbind (intern ("minibuffer-completing-file-name"),
+           Vminibuffer_completing_file_name);
   if (EQ (Vminibuffer_completing_file_name, Qlambda))
     Vminibuffer_completing_file_name = Qnil;
 
@@ -423,8 +410,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
     {
       if (CONSP (initial))
        {
-         Lisp_Object backup_n = Fcdr (initial);
-         initial = Fcar (initial);
+         Lisp_Object backup_n = XCDR (initial);
+         initial = XCAR (initial);
          CHECK_STRING (initial);
          if (!NILP (backup_n))
            {
@@ -475,23 +462,28 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
                                         expflag, histvar, histpos, defalt,
                                         allow_props, inherit_input_method);
       UNGCPRO;
-      return unbind_to (count, val);
+      dynwind_end ();
+      return val;
     }
 
   /* Choose the minibuffer window and frame, and take action on them.  */
 
+  /* Prepare for restoring the current buffer since choose_minibuf_frame
+     calling Fset_frame_selected_window may change it (Bug#12766).  */
+  record_unwind_protect (restore_buffer, Fcurrent_buffer ());
+
   choose_minibuf_frame ();
 
-  record_unwind_protect (choose_minibuf_frame_1, Qnil);
+  record_unwind_protect_void (choose_minibuf_frame);
 
-  record_unwind_protect (Fset_window_configuration,
+  record_unwind_protect (restore_window_configuration,
                         Fcurrent_window_configuration (Qnil));
 
   /* If the minibuffer window is on a different frame, save that
      frame's configuration too.  */
   mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
   if (!EQ (mini_frame, selected_frame))
-    record_unwind_protect (Fset_window_configuration,
+    record_unwind_protect (restore_window_configuration,
                           Fcurrent_window_configuration (mini_frame));
 
   /* If the minibuffer is on an iconified or invisible frame,
@@ -522,14 +514,14 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
                                         Fcons (Vminibuffer_history_variable,
                                                minibuf_save_list))))));
 
-  record_unwind_protect (read_minibuf_unwind, Qnil);
+  record_unwind_protect_void (read_minibuf_unwind);
   minibuf_level++;
   /* We are exiting the minibuffer one way or the other, so run the hook.
      It should be run before unwinding the minibuf settings.  Do it
      separately from read_minibuf_unwind because we need to make sure that
      read_minibuf_unwind is fully executed even if exit-minibuffer-hook
      signals an error.  --Stef  */
-  record_unwind_protect (run_exit_minibuf_hook, Qnil);
+  record_unwind_protect_void (run_exit_minibuf_hook);
 
   /* Now that we can restore all those variables, start changing them.  */
 
@@ -546,6 +538,14 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
   if (!NILP (Vminibuffer_completing_file_name))
     Vminibuffer_completing_file_name = Qlambda;
 
+  /* If variable is unbound, make it nil.  */
+  histval = find_symbol_value (Vminibuffer_history_variable);
+  if (EQ (histval, Qunbound))
+    {
+      Fset (Vminibuffer_history_variable, Qnil);
+      histval = Qnil;
+    }
+
   if (inherit_input_method)
     {
       /* `current-input-method' is buffer local.  So, remember it in
@@ -561,11 +561,11 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
 
   /* Defeat (setq-default truncate-lines t), since truncated lines do
      not work correctly in minibuffers.  (Bug#5715, etc)  */
-  BVAR (current_buffer, truncate_lines) = Qnil;
+  bset_truncate_lines (current_buffer, Qnil);
 
   /* If appropriate, copy enable-multibyte-characters into the minibuffer.  */
   if (inherit_input_method)
-    BVAR (current_buffer, enable_multibyte_characters) = enable_multibyte;
+    bset_enable_multibyte_characters (current_buffer, enable_multibyte);
 
   /* The current buffer's default directory is usually the right thing
      for our minibuffer here.  However, if you're typing a command at
@@ -576,24 +576,18 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
      you think of something better to do?  Find another buffer with a
      better directory, and use that one instead.  */
   if (STRINGP (ambient_dir))
-    BVAR (current_buffer, directory) = ambient_dir;
+    bset_directory (current_buffer, ambient_dir);
   else
     {
-      Lisp_Object buf_list;
-
-      for (buf_list = Vbuffer_alist;
-          CONSP (buf_list);
-          buf_list = XCDR (buf_list))
-       {
-         Lisp_Object other_buf;
+      Lisp_Object tail, buf;
 
-         other_buf = XCDR (XCAR (buf_list));
-         if (STRINGP (BVAR (XBUFFER (other_buf), directory)))
-           {
-             BVAR (current_buffer, directory) = BVAR (XBUFFER (other_buf), directory);
-             break;
-           }
-       }
+      FOR_EACH_LIVE_BUFFER (tail, buf)
+       if (STRINGP (BVAR (XBUFFER (buf), directory)))
+         {
+           bset_directory (current_buffer,
+                           BVAR (XBUFFER (buf), directory));
+           break;
+         }
     }
 
   if (!EQ (mini_frame, selected_frame))
@@ -615,20 +609,24 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
 
       if (! NILP (mini_window) && ! EQ (mini_window, minibuf_window)
          && !NILP (Fwindow_minibuffer_p (mini_window)))
-       Fset_window_buffer (mini_window, empty_minibuf, Qnil);
+       /* Use set_window_buffer instead of Fset_window_buffer (see
+          discussion of bug#11984, bug#12025, bug#12026).  */
+       set_window_buffer (mini_window, empty_minibuf, 0, 0);
     }
 
   /* Display this minibuffer in the proper window.  */
-  Fset_window_buffer (minibuf_window, Fcurrent_buffer (), Qnil);
+  /* Use set_window_buffer instead of Fset_window_buffer (see
+     discussion of bug#11984, bug#12025, bug#12026).  */
+  set_window_buffer (minibuf_window, Fcurrent_buffer (), 0, 0);
   Fselect_window (minibuf_window, Qnil);
-  XSETFASTINT (XWINDOW (minibuf_window)->hscroll, 0);
+  XWINDOW (minibuf_window)->hscroll = 0;
 
   Fmake_local_variable (Qprint_escape_newlines);
   print_escape_newlines = 1;
 
   /* Erase the buffer.  */
   {
-    ptrdiff_t count1 = SPECPDL_INDEX ();
+    dynwind_begin ();
     specbind (Qinhibit_read_only, Qt);
     specbind (Qinhibit_modification_hooks, Qt);
     Ferase_buffer ();
@@ -650,7 +648,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
        Fadd_text_properties (make_number (BEG), make_number (PT),
                              Vminibuffer_prompt_properties, Qnil);
       }
-    unbind_to (count1, Qnil);
+    dynwind_end ();
   }
 
   minibuf_prompt_width = current_column ();
@@ -663,7 +661,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
     }
 
   clear_message (1, 1);
-  BVAR (current_buffer, keymap) = map;
+  bset_keymap (current_buffer, map);
 
   /* Turn on an input method stored in INPUT_METHOD if any.  */
   if (STRINGP (input_method) && !NILP (Ffboundp (Qactivate_input_method)))
@@ -672,7 +670,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
   Frun_hooks (1, &Qminibuffer_setup_hook);
 
   /* Don't allow the user to undo past this point.  */
-  BVAR (current_buffer, undo_list) = Qnil;
+  bset_undo_list (current_buffer, Qnil);
 
   recursive_edit_1 ();
 
@@ -685,12 +683,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
       XWINDOW (minibuf_window)->cursor.x = 0;
       XWINDOW (minibuf_window)->must_be_updated_p = 1;
       update_frame (XFRAME (selected_frame), 1, 1);
-      {
-        struct frame *f = XFRAME (XWINDOW (minibuf_window)->frame);
-        struct redisplay_interface *rif = FRAME_RIF (f);
-        if (rif && rif->flush_display)
-          rif->flush_display (f);
-      }
+      flush_frame (XFRAME (XWINDOW (minibuf_window)->frame));
     }
 
   /* Make minibuffer contents into a string.  */
@@ -721,13 +714,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
     {
       /* If the caller wanted to save the value read on a history list,
         then do so if the value is not already the front of the list.  */
-      Lisp_Object histval;
-
-      /* If variable is unbound, make it nil.  */
-
-      histval = find_symbol_value (Vminibuffer_history_variable);
-      if (EQ (histval, Qunbound))
-       Fset (Vminibuffer_history_variable, Qnil);
 
       /* The value of the history variable must be a cons or nil.  Other
         values are unacceptable.  We silently ignore these values.  */
@@ -768,7 +754,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
   /* The appropriate frame will get selected
      in set-window-configuration.  */
   UNGCPRO;
-  return unbind_to (count, val);
+  dynwind_end ();
+  return val;
 }
 
 /* Return a buffer to be used as the minibuffer at depth `depth'.
@@ -785,14 +772,14 @@ get_minibuffer (EMACS_INT depth)
   tail = Fnthcdr (num, Vminibuffer_list);
   if (NILP (tail))
     {
-      tail = Fcons (Qnil, Qnil);
+      tail = list1 (Qnil);
       Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
     }
   buf = Fcar (tail);
-  if (NILP (buf) || NILP (BVAR (XBUFFER (buf), name)))
+  if (NILP (buf) || !BUFFER_LIVE_P (XBUFFER (buf)))
     {
-      sprintf (name, " *Minibuf-%"pI"d*", depth);
-      buf = Fget_buffer_create (build_string (name));
+      buf = Fget_buffer_create
+       (make_formatted_string (name, " *Minibuf-%"pI"d*", depth));
 
       /* Although the buffer's name starts with a space, undo should be
         enabled in it.  */
@@ -802,37 +789,35 @@ get_minibuffer (EMACS_INT depth)
     }
   else
     {
-      ptrdiff_t count = SPECPDL_INDEX ();
-      /* `reset_buffer' blindly sets the list of overlays to NULL, so we
-        have to empty the list, otherwise we end up with overlays that
-        think they belong to this buffer while the buffer doesn't know about
-        them any more.  */
+      dynwind_begin ();
+      /* We have to empty both overlay lists.  Otherwise we end
+        up with overlays that think they belong to this buffer
+        while the buffer doesn't know about them any more.  */
       delete_all_overlays (XBUFFER (buf));
       reset_buffer (XBUFFER (buf));
-      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      record_unwind_current_buffer ();
       Fset_buffer (buf);
       if (!NILP (Ffboundp (intern ("minibuffer-inactive-mode"))))
        call0 (intern ("minibuffer-inactive-mode"));
       else
         Fkill_all_local_variables ();
-      unbind_to (count, Qnil);
+      dynwind_end ();
     }
 
   return buf;
 }
 
-static Lisp_Object
-run_exit_minibuf_hook (Lisp_Object data)
+static void
+run_exit_minibuf_hook (void)
 {
   safe_run_hooks (Qminibuffer_exit_hook);
-  return Qnil;
 }
 
 /* This function is called on exiting minibuffer, whether normally or
    not, and it restores the current window, buffer, etc.  */
 
-static Lisp_Object
-read_minibuf_unwind (Lisp_Object data)
+static void
+read_minibuf_unwind (void)
 {
   Lisp_Object old_deactivate_mark;
   Lisp_Object window;
@@ -844,7 +829,7 @@ read_minibuf_unwind (Lisp_Object data)
   window = minibuf_window;
   /* To keep things predictable, in case it matters, let's be in the
      minibuffer when we reset the relevant variables.  */
-  Fset_buffer (XWINDOW (window)->buffer);
+  Fset_buffer (XWINDOW (window)->contents);
 
   /* Restore prompt, etc, from outer minibuffer level.  */
   minibuf_prompt = Fcar (minibuf_save_list);
@@ -870,14 +855,14 @@ read_minibuf_unwind (Lisp_Object data)
 
   /* Erase the minibuffer we were using at this level.  */
   {
-    ptrdiff_t count = SPECPDL_INDEX ();
+    dynwind_begin ();
     /* Prevent error in erase-buffer.  */
     specbind (Qinhibit_read_only, Qt);
     specbind (Qinhibit_modification_hooks, Qt);
     old_deactivate_mark = Vdeactivate_mark;
     Ferase_buffer ();
     Vdeactivate_mark = old_deactivate_mark;
-    unbind_to (count, Qnil);
+    dynwind_end ();
   }
 
   /* When we get to the outmost level, make sure we resize the
@@ -885,17 +870,11 @@ read_minibuf_unwind (Lisp_Object data)
   if (minibuf_level == 0)
     resize_mini_window (XWINDOW (window), 0);
 
-  /* Make sure minibuffer window is erased, not ignored.  */
-  windows_or_buffers_changed++;
-  XSETFASTINT (XWINDOW (window)->last_modified, 0);
-  XSETFASTINT (XWINDOW (window)->last_overlay_modified, 0);
-
   /* In case the previous minibuffer displayed in this miniwindow is
      dead, we may keep displaying this buffer (tho it's inactive), so reset it,
      to make sure we don't leave around bindings and stuff which only
      made sense during the read_minibuf invocation.  */
   call0 (intern ("minibuffer-inactive-mode"));
-  return Qnil;
 }
 \f
 
@@ -986,42 +965,14 @@ and some related functions, which use zero-indexing for POSITION.  */)
   return val;
 }
 
-DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
-       doc: /* Return a Lisp object read using the minibuffer, unevaluated.
-Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
-is a string to insert in the minibuffer before reading.
-\(INITIAL-CONTENTS can also be a cons of a string and an integer.
-Such arguments are used as in `read-from-minibuffer'.)  */)
-  (Lisp_Object prompt, Lisp_Object initial_contents)
-{
-  CHECK_STRING (prompt);
-  return read_minibuf (Vminibuffer_local_map, initial_contents,
-                      prompt, 1, Qminibuffer_history,
-                      make_number (0), Qnil, 0, 0);
-}
-
-DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0,
-       doc: /* Return value of Lisp expression read using the minibuffer.
-Prompt with PROMPT.  If non-nil, optional second arg INITIAL-CONTENTS
-is a string to insert in the minibuffer before reading.
-\(INITIAL-CONTENTS can also be a cons of a string and an integer.
-Such arguments are used as in `read-from-minibuffer'.)  */)
-  (Lisp_Object prompt, Lisp_Object initial_contents)
-{
-  return Feval (read_minibuf (Vread_expression_map, initial_contents,
-                             prompt, 1, Qread_expression_history,
-                             make_number (0), Qnil, 0, 0),
-               Qnil);
-}
-
 /* Functions that use the minibuffer to read various things.  */
 
 DEFUN ("read-string", Fread_string, Sread_string, 1, 5, 0,
        doc: /* Read a string from the minibuffer, prompting with string PROMPT.
 If non-nil, second arg INITIAL-INPUT is a string to insert before reading.
-  This argument has been superseded by DEFAULT-VALUE and should normally
-  be nil in new code.  It behaves as in `read-from-minibuffer'.  See the
-  documentation string of that function for details.
+  This argument has been superseded by DEFAULT-VALUE and should normally be nil
+  in new code.  It behaves as INITIAL-CONTENTS in `read-from-minibuffer' (which
+  see).
 The third arg HISTORY, if non-nil, specifies a history list
   and optionally the initial position in the list.
 See `read-from-minibuffer' for details of HISTORY argument.
@@ -1034,11 +985,20 @@ Fifth arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits
   (Lisp_Object prompt, Lisp_Object initial_input, Lisp_Object history, Lisp_Object default_value, Lisp_Object inherit_input_method)
 {
   Lisp_Object val;
+  dynwind_begin ();
+
+  /* Just in case we're in a recursive minibuffer, make it clear that the
+     previous minibuffer's completion table does not apply to the new
+     minibuffer.
+     FIXME: `minibuffer-completion-table' should be buffer-local instead.  */
+  specbind (Qminibuffer_completion_table, Qnil);
+
   val = Fread_from_minibuffer (prompt, initial_input, Qnil,
                               Qnil, history, default_value,
                               inherit_input_method);
   if (STRINGP (val) && SCHARS (val) == 0 && ! NILP (default_value))
     val = CONSP (default_value) ? XCAR (default_value) : default_value;
+  dynwind_end ();
   return val;
 }
 
@@ -1136,7 +1096,7 @@ function, instead of the usual behavior.  */)
   Lisp_Object args[4], result;
   char *s;
   ptrdiff_t len;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
 
   if (BUFFERP (def))
     def = BVAR (XBUFFER (def), name);
@@ -1185,7 +1145,8 @@ function, instead of the usual behavior.  */)
       args[3] = require_match;
       result = Ffuncall (4, args);
     }
-  return unbind_to (count, result);
+  dynwind_end ();
+  return result;
 }
 \f
 static Lisp_Object
@@ -1242,13 +1203,10 @@ is used to further constrain the set of candidates.  */)
     type = (HASH_TABLE_P (collection) ? hash_table
            : VECTORP (collection) ? obarray_table
            : ((NILP (collection)
-               || (CONSP (collection)
-                   && (!SYMBOLP (XCAR (collection))
-                       || NILP (XCAR (collection)))))
+               || (CONSP (collection) && !FUNCTIONP (collection)))
               ? list_table : function_table));
   ptrdiff_t idx = 0, obsize = 0;
   int matchcount = 0;
-  ptrdiff_t bindcount = -1;
   Lisp_Object bucket, zero, end, tem;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
@@ -1265,7 +1223,7 @@ is used to further constrain the set of candidates.  */)
     {
       collection = check_obarray (collection);
       obsize = ASIZE (collection);
-      bucket = XVECTOR (collection)->contents[idx];
+      bucket = AREF (collection, idx);
     }
 
   while (1)
@@ -1300,7 +1258,7 @@ is used to further constrain the set of candidates.  */)
            break;
          else
            {
-             bucket = XVECTOR (collection)->contents[idx];
+             bucket = AREF (collection, idx);
              continue;
            }
        }
@@ -1333,18 +1291,17 @@ is used to further constrain the set of candidates.  */)
 
          /* Ignore this element if it fails to match all the regexps.  */
          {
+            dynwind_begin ();
+            specbind (Qcase_fold_search,
+                      completion_ignore_case ? Qt : Qnil);
            for (regexps = Vcompletion_regexp_list; CONSP (regexps);
                 regexps = XCDR (regexps))
              {
-               if (bindcount < 0) {
-                 bindcount = SPECPDL_INDEX ();
-                 specbind (Qcase_fold_search,
-                           completion_ignore_case ? Qt : Qnil);
-               }
                tem = Fstring_match (XCAR (regexps), eltstring, zero);
                if (NILP (tem))
                  break;
              }
+            dynwind_end ();
            if (CONSP (regexps))
              continue;
          }
@@ -1358,11 +1315,6 @@ is used to further constrain the set of candidates.  */)
                tem = Fcommandp (elt, Qnil);
              else
                {
-                 if (bindcount >= 0)
-                   {
-                     unbind_to (bindcount, Qnil);
-                     bindcount = -1;
-                   }
                  GCPRO4 (tail, string, eltstring, bestmatch);
                  tem = (type == hash_table
                         ? call2 (predicate, elt,
@@ -1390,12 +1342,7 @@ is used to further constrain the set of candidates.  */)
                                      eltstring, zero,
                                      make_number (compare),
                                      completion_ignore_case ? Qt : Qnil);
-             if (EQ (tem, Qt))
-               matchsize = compare;
-             else if (XINT (tem) < 0)
-               matchsize = - XINT (tem) - 1;
-             else
-               matchsize = XINT (tem) - 1;
+             matchsize = EQ (tem, Qt) ? compare : eabs (XINT (tem)) - 1;
 
              if (completion_ignore_case)
                {
@@ -1432,7 +1379,7 @@ is used to further constrain the set of candidates.  */)
              if (bestmatchsize != SCHARS (eltstring)
                  || bestmatchsize != matchsize)
                /* Don't count the same string multiple times.  */
-               matchcount++;
+               matchcount += matchcount <= 1;
              bestmatchsize = matchsize;
              if (matchsize <= SCHARS (string)
                  /* If completion-ignore-case is non-nil, don't
@@ -1446,11 +1393,6 @@ is used to further constrain the set of candidates.  */)
        }
     }
 
-  if (bindcount >= 0) {
-    unbind_to (bindcount, Qnil);
-    bindcount = -1;
-  }
-
   if (NILP (bestmatch))
     return Qnil;               /* No completions found.  */
   /* If we are ignoring case, and there is no exact match,
@@ -1508,11 +1450,8 @@ with a space are ignored unless STRING itself starts with a space.  */)
   Lisp_Object allmatches;
   int type = HASH_TABLE_P (collection) ? 3
     : VECTORP (collection) ? 2
-    : NILP (collection) || (CONSP (collection)
-                           && (!SYMBOLP (XCAR (collection))
-                               || NILP (XCAR (collection))));
+    : NILP (collection) || (CONSP (collection) && !FUNCTIONP (collection));
   ptrdiff_t idx = 0, obsize = 0;
-  ptrdiff_t bindcount = -1;
   Lisp_Object bucket, tem, zero;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
@@ -1528,7 +1467,7 @@ with a space are ignored unless STRING itself starts with a space.  */)
     {
       collection = check_obarray (collection);
       obsize = ASIZE (collection);
-      bucket = XVECTOR (collection)->contents[idx];
+      bucket = AREF (collection, idx);
     }
 
   while (1)
@@ -1563,7 +1502,7 @@ with a space are ignored unless STRING itself starts with a space.  */)
            break;
          else
            {
-             bucket = XVECTOR (collection)->contents[idx];
+             bucket = AREF (collection, idx);
              continue;
            }
        }
@@ -1603,18 +1542,17 @@ with a space are ignored unless STRING itself starts with a space.  */)
 
          /* Ignore this element if it fails to match all the regexps.  */
          {
+            dynwind_begin ();
+            specbind (Qcase_fold_search,
+                      completion_ignore_case ? Qt : Qnil);
            for (regexps = Vcompletion_regexp_list; CONSP (regexps);
                 regexps = XCDR (regexps))
              {
-               if (bindcount < 0) {
-                 bindcount = SPECPDL_INDEX ();
-                 specbind (Qcase_fold_search,
-                           completion_ignore_case ? Qt : Qnil);
-               }
                tem = Fstring_match (XCAR (regexps), eltstring, zero);
                if (NILP (tem))
                  break;
              }
+            dynwind_end ();
            if (CONSP (regexps))
              continue;
          }
@@ -1628,10 +1566,6 @@ with a space are ignored unless STRING itself starts with a space.  */)
                tem = Fcommandp (elt, Qnil);
              else
                {
-                 if (bindcount >= 0) {
-                   unbind_to (bindcount, Qnil);
-                   bindcount = -1;
-                 }
                  GCPRO4 (tail, eltstring, allmatches, string);
                  tem = type == 3
                    ? call2 (predicate, elt,
@@ -1646,11 +1580,6 @@ with a space are ignored unless STRING itself starts with a space.  */)
        }
     }
 
-  if (bindcount >= 0) {
-    unbind_to (bindcount, Qnil);
-    bindcount = -1;
-  }
-
   return Fnreverse (allmatches);
 }
 \f
@@ -1688,7 +1617,7 @@ If INITIAL-INPUT is non-nil, insert it in the minibuffer initially,
   functions, which use one-indexing for POSITION.)  This feature is
   deprecated--it is best to pass nil for INITIAL-INPUT and supply the
   default value DEF instead.  The user can yank the default value into
-  the minibuffer easily using \\[next-history-element].
+  the minibuffer easily using \\<minibuffer-local-map>\\[next-history-element].
 
 HIST, if non-nil, specifies a history list and optionally the initial
   position in the list.  It can be a symbol, which is the history list
@@ -1739,9 +1668,7 @@ the values STRING, PREDICATE and `lambda'.  */)
 
   CHECK_STRING (string);
 
-  if ((CONSP (collection)
-       && (!SYMBOLP (XCAR (collection)) || NILP (XCAR (collection))))
-      || NILP (collection))
+  if (NILP (collection) || (CONSP (collection) && !FUNCTIONP (collection)))
     {
       tem = Fassoc_string (string, collection, completion_ignore_case ? Qt : Qnil);
       if (NILP (tem))
@@ -1771,7 +1698,7 @@ the values STRING, PREDICATE and `lambda'.  */)
        {
          for (i = ASIZE (collection) - 1; i >= 0; i--)
            {
-             tail = XVECTOR (collection)->contents[i];
+             tail = AREF (collection, i);
              if (SYMBOLP (tail))
                while (1)
                  {
@@ -1796,18 +1723,22 @@ the values STRING, PREDICATE and `lambda'.  */)
   else if (HASH_TABLE_P (collection))
     {
       struct Lisp_Hash_Table *h = XHASH_TABLE (collection);
+      Lisp_Object key = Qnil;
       i = hash_lookup (h, string, NULL);
       if (i >= 0)
        tem = HASH_KEY (h, i);
       else
        for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
          if (!NILP (HASH_HASH (h, i))
+             && (key = HASH_KEY (h, i),
+                 SYMBOLP (key) ? key = Fsymbol_name (key) : key,
+                 STRINGP (key))
              && EQ (Fcompare_strings (string, make_number (0), Qnil,
-                                      HASH_KEY (h, i), make_number (0) , Qnil,
+                                      key, make_number (0) , Qnil,
                                       completion_ignore_case ? Qt : Qnil),
                     Qt))
            {
-             tem = HASH_KEY (h, i);
+             tem = key;
              break;
            }
       if (!STRINGP (tem))
@@ -1819,17 +1750,20 @@ the values STRING, PREDICATE and `lambda'.  */)
   /* Reject this element if it fails to match all the regexps.  */
   if (CONSP (Vcompletion_regexp_list))
     {
-      ptrdiff_t count = SPECPDL_INDEX ();
+      dynwind_begin ();
       specbind (Qcase_fold_search, completion_ignore_case ? Qt : Qnil);
       for (regexps = Vcompletion_regexp_list; CONSP (regexps);
           regexps = XCDR (regexps))
        {
          if (NILP (Fstring_match (XCAR (regexps),
                                   SYMBOLP (tem) ? string : tem,
-                                  Qnil)))
-           return unbind_to (count, Qnil);
+                                  Qnil))){
+           
+             dynwind_end ();
+           return Qnil;
+           }
        }
-      unbind_to (count, Qnil);
+      dynwind_end ();
     }
 
   /* Finally, check the predicate.  */
@@ -1844,15 +1778,14 @@ the values STRING, PREDICATE and `lambda'.  */)
 }
 
 static Lisp_Object Qmetadata;
-extern Lisp_Object Qbuffer;
 
 DEFUN ("internal-complete-buffer", Finternal_complete_buffer, Sinternal_complete_buffer, 3, 3, 0,
        doc: /* Perform completion on buffer names.
-If the argument FLAG is nil, invoke `try-completion', if it's t, invoke
-`all-completions', otherwise invoke `test-completion'.
+STRING and PREDICATE have the same meanings as in `try-completion',
+`all-completions', and `test-completion'.
 
-The arguments STRING and PREDICATE are as in `try-completion',
-`all-completions', and `test-completion'.  */)
+If FLAG is nil, invoke `try-completion'; if it is t, invoke
+`all-completions'; otherwise invoke `test-completion'.  */)
   (Lisp_Object string, Lisp_Object predicate, Lisp_Object flag)
 {
   if (NILP (flag))
@@ -1884,7 +1817,7 @@ The arguments STRING and PREDICATE are as in `try-completion',
   else if (EQ (flag, Qlambda))
     return Ftest_completion (string, Vbuffer_alist, predicate);
   else if (EQ (flag, Qmetadata))
-    return Fcons (Qmetadata, Fcons (Fcons (Qcategory, Qbuffer), Qnil));
+    return list2 (Qmetadata, Fcons (Qcategory, Qbuffer));
   else
     return Qnil;
 }
@@ -1955,6 +1888,8 @@ init_minibuf_once (void)
 void
 syms_of_minibuf (void)
 {
+#include "minibuf.x"
+
   minibuf_level = 0;
   minibuf_prompt = Qnil;
   staticpro (&minibuf_prompt);
@@ -2021,7 +1956,7 @@ A value of t means no truncation.
 This variable only affects history lists that don't specify their own
 maximum lengths.  Setting the `history-length' property of a history
 variable overrides this default.  */);
-  XSETFASTINT (Vhistory_length, 30);
+  XSETFASTINT (Vhistory_length, 100);
 
   DEFVAR_BOOL ("history-delete-duplicates", history_delete_duplicates,
               doc: /* Non-nil means to delete duplicates in history.
@@ -2128,36 +2063,5 @@ These are in addition to the basic `field' property, and stickiness
 properties.  */);
   /* We use `intern' here instead of Qread_only to avoid
      initialization-order problems.  */
-  Vminibuffer_prompt_properties
-    = Fcons (intern_c_string ("read-only"), Fcons (Qt, Qnil));
-
-  DEFVAR_LISP ("read-expression-map", Vread_expression_map,
-              doc: /* Minibuffer keymap used for reading Lisp expressions.  */);
-  Vread_expression_map = Qnil;
-
-  defsubr (&Sactive_minibuffer_window);
-  defsubr (&Sset_minibuffer_window);
-  defsubr (&Sread_from_minibuffer);
-  defsubr (&Seval_minibuffer);
-  defsubr (&Sread_minibuffer);
-  defsubr (&Sread_string);
-  defsubr (&Sread_command);
-  defsubr (&Sread_variable);
-  defsubr (&Sinternal_complete_buffer);
-  defsubr (&Sread_buffer);
-  defsubr (&Sread_no_blanks_input);
-  defsubr (&Sminibuffer_depth);
-  defsubr (&Sminibuffer_prompt);
-
-  defsubr (&Sminibufferp);
-  defsubr (&Sminibuffer_prompt_end);
-  defsubr (&Sminibuffer_contents);
-  defsubr (&Sminibuffer_contents_no_properties);
-  defsubr (&Sminibuffer_completion_contents);
-
-  defsubr (&Stry_completion);
-  defsubr (&Sall_completions);
-  defsubr (&Stest_completion);
-  defsubr (&Sassoc_string);
-  defsubr (&Scompleting_read);
+  Vminibuffer_prompt_properties = list2 (intern_c_string ("read-only"), Qt);
 }