(SWITCH_ENUM_CAST): New macro.
[bpt/emacs.git] / src / minibuf.c
index c160711..74cf3d7 100644 (file)
@@ -1,5 +1,5 @@
 /* Minibuffer input and completion.
-   Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -29,24 +29,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
+extern int quit_char;
+
 /* List of buffers for use as minibuffers.
-  The first element of the list is used for the outermost minibuffer invocation,
-  the next element is used for a recursive minibuffer invocation, etc.
-  The list is extended at the end as deeped minibuffer recursions are encountered. */
+   The first element of the list is used for the outermost minibuffer
+   invocation, the next element is used for a recursive minibuffer
+   invocation, etc.  The list is extended at the end as deeper
+   minibuffer recursions are encountered.  */
 Lisp_Object Vminibuffer_list;
 
-struct minibuf_save_data
-  {
-    char *prompt;
-    int prompt_width;
-    Lisp_Object help_form;
-    Lisp_Object current_prefix_arg;
-    Lisp_Object history_position;
-    Lisp_Object history_variable;
-  };
-
-int minibuf_save_vector_size;
-struct minibuf_save_data *minibuf_save_vector;
+/* Data to remember during recursive minibuffer invocations  */
+Lisp_Object minibuf_save_list;
 
 /* Depth in minibuffer invocations.  */
 int minibuf_level;
@@ -77,14 +70,19 @@ Lisp_Object Qminibuffer_history;
 
 Lisp_Object Qread_file_name_internal;
 
-/* Normal hook for entry to minibuffer.  */
+/* Normal hooks for entry to and exit from minibuffer.  */
 
 Lisp_Object Qminibuffer_setup_hook, Vminibuffer_setup_hook;
+Lisp_Object Qminibuffer_exit_hook, Vminibuffer_exit_hook;
 
 /* Nonzero means completion ignores case.  */
 
 int completion_ignore_case;
 
+/* List of regexps that should restrict possible completions.  */
+
+Lisp_Object Vcompletion_regexp_list;
+
 /* Nonzero means raise the minibuffer frame when the minibuffer
    is entered.  */
 
@@ -96,6 +94,10 @@ int minibuffer_auto_raise;
 static Lisp_Object last_exact_completion;
 
 Lisp_Object Quser_variable_p;
+
+/* Non-nil means it is the window for C-M-v to scroll
+   when the minibuffer is selected.  */
+extern Lisp_Object Vminibuf_scroll_window;
 \f
 /* Actual minibuffer invocation. */
 
@@ -109,11 +111,10 @@ Lisp_Object read_minibuf ();
    with initial position HISTPOS.  (BACKUP_N should be <= 0.)
 
    Normally return the result as a string (the text that was read),
-   but if EXPFLAG is non-nil, read it and return the object read.
+   but if EXPFLAG is nonzero, 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, or as the object that resulted iff
-   EXPFLAG is non-nil.  */
+   the list as the string that was read.  */
 
 Lisp_Object
 read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
@@ -125,16 +126,22 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
      Lisp_Object histvar;
      Lisp_Object histpos;
 {
-  register Lisp_Object val;
+  Lisp_Object val;
   int count = specpdl_ptr - specpdl;
   Lisp_Object mini_frame;
-  struct gcpro gcpro1, gcpro2;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+
+  val = Qnil;
+  /* Don't need to protect PROMPT, HISTVAR, and HISTPOS because we
+     store them away before we can GC.  Don't need to protect
+     BACKUP_N because we use the value only if it is an integer.  */
+  GCPRO3 (map, initial, val);
 
-  if (XTYPE (prompt) != Lisp_String)
+  if (!STRINGP (prompt))
     prompt = build_string ("");
 
   /* Emacs in -batch mode calls minibuffer: print the prompt.  */
-  if (noninteractive && XTYPE (prompt) == Lisp_String)
+  if (noninteractive && STRINGP (prompt))
     printf ("%s", XSTRING (prompt)->data);
 
   if (!enable_recursive_minibuffers
@@ -145,22 +152,19 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
 #endif
     error ("Command attempted to use minibuffer while in minibuffer");
 
-  if (minibuf_level == minibuf_save_vector_size)
-    minibuf_save_vector =
-     (struct minibuf_save_data *)
-       xrealloc (minibuf_save_vector,
-                (minibuf_save_vector_size *= 2)
-                * sizeof (struct minibuf_save_data)); 
-  minibuf_save_vector[minibuf_level].prompt = minibuf_prompt;
-  minibuf_save_vector[minibuf_level].prompt_width = minibuf_prompt_width;
-  minibuf_prompt_width = 0;
-  /* >> Why is this done this way rather than binding these variables? */
-  minibuf_save_vector[minibuf_level].help_form = Vhelp_form;
-  minibuf_save_vector[minibuf_level].current_prefix_arg = Vcurrent_prefix_arg;
-  minibuf_save_vector[minibuf_level].history_position = Vminibuffer_history_position;
-  minibuf_save_vector[minibuf_level].history_variable = Vminibuffer_history_variable;
-  GCPRO2 (minibuf_save_vector[minibuf_level].help_form,
-         minibuf_save_vector[minibuf_level].current_prefix_arg);
+  /* Could we simply bind these variables instead?  */
+  minibuf_save_list
+    = Fcons (minibuf_prompt,
+            Fcons (make_number (minibuf_prompt_width),
+                   Fcons (Vhelp_form,
+                          Fcons (Vcurrent_prefix_arg,
+                                 Fcons (Vminibuffer_history_position,
+                                        Fcons (Vminibuffer_history_variable,
+                                               minibuf_save_list))))));
+  minibuf_prompt_width = 0;    /* xdisp.c puts in the right value.  */
+  minibuf_prompt = Fcopy_sequence (prompt);
+  Vminibuffer_history_position = histpos;
+  Vminibuffer_history_variable = histvar;
 
   record_unwind_protect (Fset_window_configuration,
                         Fcurrent_window_configuration (Qnil));
@@ -168,10 +172,15 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   /* If the minibuffer window is on a different frame, save that
      frame's configuration too.  */
 #ifdef MULTI_FRAME
-  XSET (mini_frame, Lisp_Frame, WINDOW_FRAME (XWINDOW (minibuf_window)));
+  mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
   if (XFRAME (mini_frame) != selected_frame)
     record_unwind_protect (Fset_window_configuration,
                           Fcurrent_window_configuration (mini_frame));
+
+  /* If the minibuffer is on an iconified or invisible frame,
+     make it visible now.  */
+  Fmake_frame_visible (mini_frame);
+
   if (minibuffer_auto_raise)
     Fraise_frame (mini_frame);
 #endif
@@ -187,7 +196,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
      up Emacs and buf's default directory is Qnil.  Here's a hack; can
      you think of something better to do?  Find another buffer with a
      better directory, and use that one instead.  */
-  if (XTYPE (val) == Lisp_String)
+  if (STRINGP (val))
     current_buffer->directory = val;
   else
     {
@@ -197,9 +206,10 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
           CONSP (buf_list);
           buf_list = XCONS (buf_list)->cdr)
        {
-         Lisp_Object other_buf = XCONS (XCONS (buf_list)->car)->cdr;
+         Lisp_Object other_buf;
 
-         if (XTYPE (XBUFFER (other_buf)->directory) == Lisp_String)
+         other_buf = XCONS (XCONS (buf_list)->car)->cdr;
+         if (STRINGP (XBUFFER (other_buf)->directory))
            {
              current_buffer->directory = XBUFFER (other_buf)->directory;
              break;
@@ -208,7 +218,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
     }
 
 #ifdef MULTI_FRAME
-  Fredirect_frame_focus (Fselected_frame (), mini_frame);
+  if (XFRAME (mini_frame) != selected_frame)
+    Fredirect_frame_focus (Fselected_frame (), mini_frame);
 #endif
   Fmake_local_variable (Qprint_escape_newlines);
   print_escape_newlines = 1;
@@ -218,7 +229,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   Vminibuf_scroll_window = selected_window;
   Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
   Fselect_window (minibuf_window);
-  XFASTINT (XWINDOW (minibuf_window)->hscroll) = 0;
+  XSETFASTINT (XWINDOW (minibuf_window)->hscroll, 0);
 
   Ferase_buffer ();
   minibuf_level++;
@@ -226,23 +237,22 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   if (!NILP (initial))
     {
       Finsert (1, &initial);
-      if (!NILP (backup_n) && XTYPE (backup_n) == Lisp_Int)
+      if (!NILP (backup_n) && INTEGERP (backup_n))
        Fforward_char (backup_n);
     }
 
-  minibuf_prompt = (char *) alloca (XSTRING (prompt)->size + 1);
-  bcopy (XSTRING (prompt)->data, minibuf_prompt, XSTRING (prompt)->size + 1);
   echo_area_glyphs = 0;
+  /* This is in case the minibuffer-setup-hook calls Fsit_for.  */
+  previous_echo_glyphs = 0;
 
   Vhelp_form = Vminibuffer_help_form;
   current_buffer->keymap = map;
-  Vminibuffer_history_position = histpos;
-  Vminibuffer_history_variable = histvar;
 
   /* Run our hook, but not if it is empty.
      (run-hooks would do nothing if it is empty,
      but it's important to save time here in the usual case.  */
-  if (!NILP (Vminibuffer_setup_hook) && !EQ (Vminibuffer_setup_hook, Qunbound))
+  if (!NILP (Vminibuffer_setup_hook) && !EQ (Vminibuffer_setup_hook, Qunbound)
+      && !NILP (Vrun_hooks))
     call1 (Vrun_hooks, Qminibuffer_setup_hook);
 
 /* ??? MCC did redraw_screen here if switching screens.  */
@@ -265,8 +275,9 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   /* VAL is the string of minibuffer text.  */
   last_minibuf_string = val;
 
-  /* Add the value to the appropriate history list.  */
-  if (XTYPE (Vminibuffer_history_variable) == Lisp_Symbol
+  /* Add the value to the appropriate history list unless it is empty.  */
+  if (XSTRING (val)->size != 0
+      && SYMBOLP (Vminibuffer_history_variable)
       && ! EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
     {
       /* If the caller wanted to save the value read on a history list,
@@ -285,14 +296,21 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
 
   /* If Lisp form desired instead of string, parse it. */
   if (expflag)
-    val = Fread (val);
-
-  unbind_to (count, Qnil);     /* The appropriate frame will get selected
-                                  in set-window-configuration.  */
-
-  UNGCPRO;
+    {
+      Lisp_Object expr_and_pos;
+      unsigned char *p;
+
+      expr_and_pos = Fread_from_string (val, Qnil, Qnil);
+      /* Ignore trailing whitespace; any other trailing junk is an error.  */
+      for (p = XSTRING (val)->data + XINT (Fcdr (expr_and_pos)); *p; p++)
+       if (*p != ' ' && *p != '\t' && *p != '\n')
+         error ("Trailing garbage following expression");
+      val = Fcar (expr_and_pos);
+    }
 
-  return val;
+  /* The appropriate frame will get selected
+     in set-window-configuration.  */
+  RETURN_UNGCPRO (unbind_to (count, val));
 }
 
 /* Return a buffer to be used as the minibuffer at depth `depth'.
@@ -304,10 +322,10 @@ get_minibuffer (depth)
      int depth;
 {
   Lisp_Object tail, num, buf;
-  char name[14];
+  char name[24];
   extern Lisp_Object nconc2 ();
 
-  XFASTINT (num) = depth;
+  XSETFASTINT (num, depth);
   tail = Fnthcdr (num, Vminibuffer_list);
   if (NILP (tail))
     {
@@ -327,7 +345,15 @@ get_minibuffer (depth)
       XCONS (tail)->car = buf;
     }
   else
-    reset_buffer (XBUFFER (buf));
+    {
+      int count = specpdl_ptr - specpdl;
+
+      reset_buffer (XBUFFER (buf));
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      Fset_buffer (buf);
+      Fkill_all_local_variables ();
+      unbind_to (count, Qnil);
+    }
 
   return buf;
 }
@@ -339,29 +365,44 @@ void
 read_minibuf_unwind (data)
      Lisp_Object data;
 {
+  Lisp_Object old_deactivate_mark;
+
+  /* We are exiting the minibuffer one way or the other,
+     so run the hook.  */
+  if (!NILP (Vminibuffer_exit_hook) && !EQ (Vminibuffer_exit_hook, Qunbound)
+      && !NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qminibuffer_exit_hook);
+
   /* Erase the minibuffer we were using at this level.  */
   Fset_buffer (XWINDOW (minibuf_window)->buffer);
 
   /* Prevent error in erase-buffer.  */
   current_buffer->read_only = Qnil;
+
+  old_deactivate_mark = Vdeactivate_mark;
   Ferase_buffer ();
+  Vdeactivate_mark = old_deactivate_mark;
 
   /* If this was a recursive minibuffer,
      tie the minibuffer window back to the outer level minibuffer buffer */
   minibuf_level--;
   /* Make sure minibuffer window is erased, not ignored */
   windows_or_buffers_changed++;
-  XFASTINT (XWINDOW (minibuf_window)->last_modified) = 0;
-
-  /* Restore prompt from outer minibuffer */
-  minibuf_prompt = minibuf_save_vector[minibuf_level].prompt;
-  minibuf_prompt_width = minibuf_save_vector[minibuf_level].prompt_width;
-  Vhelp_form = minibuf_save_vector[minibuf_level].help_form;
-  Vcurrent_prefix_arg = minibuf_save_vector[minibuf_level].current_prefix_arg;
-  Vminibuffer_history_position
-    = minibuf_save_vector[minibuf_level].history_position;
-  Vminibuffer_history_variable
-    = minibuf_save_vector[minibuf_level].history_variable;
+  XSETFASTINT (XWINDOW (minibuf_window)->last_modified, 0);
+
+  /* Restore prompt, etc from outer minibuffer */
+  minibuf_prompt = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
+  minibuf_prompt_width = XFASTINT (Fcar (minibuf_save_list));
+  minibuf_save_list = Fcdr (minibuf_save_list);
+  Vhelp_form = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
+  Vcurrent_prefix_arg = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
+  Vminibuffer_history_position = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
+  Vminibuffer_history_variable = Fcar (minibuf_save_list);
+  minibuf_save_list = Fcdr (minibuf_save_list);
 }
 \f
 
@@ -402,7 +443,7 @@ DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1,
   CHECK_STRING (prompt, 0);
   if (!NILP (initial_contents))
     {
-      if (XTYPE (initial_contents) == Lisp_Cons)
+      if (CONSP (initial_contents))
        {
          position = Fcdr (initial_contents);
          initial_contents = Fcar (initial_contents);
@@ -421,7 +462,7 @@ DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1,
   else
     keymap = get_keymap (keymap,2);
 
-  if (XTYPE (hist) == Lisp_Symbol)
+  if (SYMBOLP (hist))
     {
       histvar = hist;
       histpos = Qnil;
@@ -434,7 +475,7 @@ DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1,
   if (NILP (histvar))
     histvar = Qminibuffer_history;
   if (NILP (histpos))
-    XFASTINT (histpos) = 0;
+    XSETFASTINT (histpos, 0);
 
   return read_minibuf (keymap, initial_contents, prompt,
                       make_number (pos), !NILP (read), histvar, histpos);
@@ -535,7 +576,7 @@ If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are a
   Lisp_Object args[3];
   struct gcpro gcpro1;
 
-  if (XTYPE (def) == Lisp_Buffer)
+  if (BUFFERP (def))
     def = XBUFFER (def)->name;
   if (!NILP (def))
     {
@@ -570,7 +611,8 @@ Whatever it returns becomes the value of `try-completion'.\n\
 If optional third argument PREDICATE is non-nil,\n\
 it is used to test each possible match.\n\
 The match is a candidate only if PREDICATE returns non-nil.\n\
-The argument given to PREDICATE is the alist element or the symbol from the obarray.")
+The argument given to PREDICATE is the alist element\n\
+or the symbol from the obarray.")
   (string, alist, pred)
      Lisp_Object string, alist, pred;
 {
@@ -584,7 +626,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   CHECK_STRING (string, 0);
-  if (!list && XTYPE (alist) != Lisp_Vector)
+  if (!list && !VECTORP (alist))
     return call3 (alist, string, pred, Qnil);
 
   bestmatch = Qnil;
@@ -622,7 +664,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
              if (XSYMBOL (bucket)->next)
                XSETSYMBOL (bucket, XSYMBOL (bucket)->next);
              else
-               XFASTINT (bucket) = 0;
+               XSETFASTINT (bucket, 0);
            }
          else if (++index >= obsize)
            break;
@@ -635,12 +677,27 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
 
       /* Is this element a possible completion? */
 
-      if (XTYPE (eltstring) == Lisp_String &&
-         XSTRING (string)->size <= XSTRING (eltstring)->size &&
-         0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
-                   XSTRING (string)->size))
+      if (STRINGP (eltstring)
+         && XSTRING (string)->size <= XSTRING (eltstring)->size
+         && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+                      XSTRING (string)->size))
        {
          /* Yes. */
+         Lisp_Object regexps;
+         Lisp_Object zero;
+         XSETFASTINT (zero, 0);
+
+         /* Ignore this element if it fails to match all the regexps.  */
+         for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+              regexps = XCONS (regexps)->cdr)
+           {
+             tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
+             if (NILP (tem))
+               break;
+           }
+         if (CONSP (regexps))
+           continue;
+
          /* Ignore this element if there is a predicate
             and the predicate doesn't like it. */
 
@@ -715,8 +772,8 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
                bestmatchsize))
     return Qt;
 
-  XFASTINT (zero) = 0;         /* Else extract the part in which */
-  XFASTINT (end) = bestmatchsize;           /* all completions agree */
+  XSETFASTINT (zero, 0);               /* Else extract the part in which */
+  XSETFASTINT (end, bestmatchsize);    /* all completions agree */
   return Fsubstring (bestmatch, zero, end);
 }
 
@@ -725,8 +782,9 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
    Return -1 if strings match,
    else number of chars that match at the beginning.  */
 
+int
 scmp (s1, s2, len)
-     register char *s1, *s2;
+     register unsigned char *s1, *s2;
      int len;
 {
   register int l = len;
@@ -743,13 +801,15 @@ scmp (s1, s2, len)
     }
   if (l == 0)
     return -1;
-  else return len - l;
+  else
+    return len - l;
 }
 \f
-DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 3, 0,
+DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 4, 0,
   "Search for partial matches to STRING in ALIST.\n\
 Each car of each element of ALIST is tested to see if it begins with STRING.\n\
 The value is a list of all the strings from ALIST that match.\n\
+\n\
 ALIST can be an obarray instead of an alist.\n\
 Then the print names of all symbols in the obarray are the possible matches.\n\
 \n\
@@ -760,9 +820,14 @@ Whatever it returns becomes the value of `all-completion'.\n\
 If optional third argument PREDICATE is non-nil,\n\
 it is used to test each possible match.\n\
 The match is a candidate only if PREDICATE returns non-nil.\n\
-The argument given to PREDICATE is the alist element or the symbol from the obarray.")
-  (string, alist, pred)
-     Lisp_Object string, alist, pred;
+The argument given to PREDICATE is the alist element\n\
+or the symbol from the obarray.\n\
+\n\
+If the optional fourth argument HIDE-SPACES is non-nil,\n\
+strings in ALIST that start with a space\n\
+are ignored unless STRING itself starts with a space.")
+  (string, alist, pred, hide_spaces)
+     Lisp_Object string, alist, pred, hide_spaces;
 {
   Lisp_Object tail, elt, eltstring;
   Lisp_Object allmatches;
@@ -772,7 +837,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   CHECK_STRING (string, 0);
-  if (!list && XTYPE (alist) != Lisp_Vector)
+  if (!list && !VECTORP (alist))
     {
       return call3 (alist, string, pred, Qt);
     }
@@ -811,7 +876,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
              if (XSYMBOL (bucket)->next)
                XSETSYMBOL (bucket, XSYMBOL (bucket)->next);
              else
-               XFASTINT (bucket) = 0;
+               XSETFASTINT (bucket, 0);
            }
          else if (++index >= obsize)
            break;
@@ -824,16 +889,32 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
 
       /* Is this element a possible completion? */
 
-      if (XTYPE (eltstring) == Lisp_String
+      if (STRINGP (eltstring)
          && XSTRING (string)->size <= XSTRING (eltstring)->size
-         /* Reject alternatives that start with space
+         /* If HIDE_SPACES, reject alternatives that start with space
             unless the input starts with space.  */
          && ((XSTRING (string)->size > 0 && XSTRING (string)->data[0] == ' ')
-             || XSTRING (eltstring)->data[0] != ' ')
+             || XSTRING (eltstring)->data[0] != ' '
+             || NILP (hide_spaces))
          && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
                       XSTRING (string)->size))
        {
          /* Yes. */
+         Lisp_Object regexps;
+         Lisp_Object zero;
+         XSETFASTINT (zero, 0);
+
+         /* Ignore this element if it fails to match all the regexps.  */
+         for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+              regexps = XCONS (regexps)->cdr)
+           {
+             tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
+             if (NILP (tem))
+               break;
+           }
+         if (CONSP (regexps))
+           continue;
+
          /* Ignore this element if there is a predicate
             and the predicate doesn't like it. */
 
@@ -871,10 +952,15 @@ Args: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT, HIST.\n\
 PROMPT is a string to prompt with; normally it ends in a colon and a space.\n\
 TABLE is an alist whose elements' cars are strings, or an obarray.\n\
 PREDICATE limits completion to a subset of TABLE.\n\
-See `try-completion' for more details on completion, TABLE, and PREDICATE.\n\
+See `try-completion' and `all-completions' for more details
+ on completion, TABLE, and PREDICATE.\n\
+\n\
 If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless\n\
- the input is (or completes to) an element of TABLE.\n\
+ the input is (or completes to) an element of TABLE or is null.\n\
  If it is also not t, Return does not exit if it does non-null completion.\n\
+If the input is null, `completing-read' returns nil,\n\
+ regardless of the value of REQUIRE-MATCH.\n\
+\n\
 If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
   If it is (STRING . POSITION), the initial input\n\
   is STRING, but point is placed POSITION characters into the string.\n\
@@ -906,7 +992,7 @@ DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
   position = Qnil;
   if (!NILP (init))
     {
-      if (XTYPE (init) == Lisp_Cons)
+      if (CONSP (init))
        {
          position = Fcdr (init);
          init = Fcar (init);
@@ -920,7 +1006,7 @@ DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
        }
     }
 
-  if (XTYPE (hist) == Lisp_Symbol)
+  if (SYMBOLP (hist))
     {
       histvar = hist;
       histpos = Qnil;
@@ -933,7 +1019,7 @@ DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
   if (NILP (histvar))
     histvar = Qminibuffer_history;
   if (NILP (histpos))
-    XFASTINT (histpos) = 0;
+    XSETFASTINT (histpos, 0);
 
   val = read_minibuf (NILP (require_match)
                      ? Vminibuffer_local_completion_map
@@ -964,17 +1050,47 @@ temp_echo_area_glyphs (m)
   SET_PT (osize);
   Vinhibit_quit = Qt;
   Fsit_for (make_number (2), Qnil, Qnil);
-  del_range (point, ZV);
+  del_range (PT, ZV);
   if (!NILP (Vquit_flag))
     {
       Vquit_flag = Qnil;
-      unread_command_events = Fcons (make_number (Ctl ('g')), Qnil);
+      Vunread_command_events = Fcons (make_number (quit_char), Qnil);
     }
   Vinhibit_quit = oinhibit;
 }
 
 Lisp_Object Fminibuffer_completion_help ();
 Lisp_Object assoc_for_completion ();
+/* A subroutine of Fintern_soft.  */
+extern Lisp_Object oblookup ();
+
+
+/* Test whether TXT is an exact completion.  */
+Lisp_Object
+test_completion (txt)
+     Lisp_Object txt;
+{
+  Lisp_Object tem;
+
+  if (CONSP (Vminibuffer_completion_table)
+      || NILP (Vminibuffer_completion_table))
+    return assoc_for_completion (txt, Vminibuffer_completion_table);
+  else if (VECTORP (Vminibuffer_completion_table))
+    {
+      /* Bypass intern-soft as that loses for nil */
+      tem = oblookup (Vminibuffer_completion_table,
+                     XSTRING (txt)->data, XSTRING (txt)->size);
+      if (!SYMBOLP (tem))
+       return Qnil;
+      else if (!NILP (Vminibuffer_completion_predicate))
+       return call1 (Vminibuffer_completion_predicate, tem);
+      else
+       return Qt;
+    }
+  else
+    return call3 (Vminibuffer_completion_table, txt,
+                 Vminibuffer_completion_predicate, Qlambda);
+}
 
 /* returns:
  * 0 no possible completion
@@ -990,21 +1106,28 @@ do_completion ()
   Lisp_Object completion, tem;
   int completedp;
   Lisp_Object last;
+  struct gcpro gcpro1, gcpro2;
 
   completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
                                Vminibuffer_completion_predicate);
   last = last_exact_completion;
   last_exact_completion = Qnil;
 
+  GCPRO2 (completion, last);
+
   if (NILP (completion))
     {
       bitch_at_user ();
       temp_echo_area_glyphs (" [No match]");
+      UNGCPRO;
       return 0;
     }
 
   if (EQ (completion, Qt))     /* exact and unique match */
-    return 1;
+    {
+      UNGCPRO;
+      return 1;
+    }
 
   /* compiler bug */
   tem = Fstring_equal (completion, Fbuffer_string());
@@ -1015,34 +1138,11 @@ do_completion ()
     }
 
   /* It did find a match.  Do we match some possibility exactly now? */
-  if (CONSP (Vminibuffer_completion_table)
-      || NILP (Vminibuffer_completion_table))
-    tem = assoc_for_completion (Fbuffer_string (),
-                               Vminibuffer_completion_table);
-  else if (XTYPE (Vminibuffer_completion_table) == Lisp_Vector)
-    {
-      /* the primitive used by Fintern_soft */
-      extern Lisp_Object oblookup ();
-
-      tem = Fbuffer_string ();
-      /* Bypass intern-soft as that loses for nil */
-      tem = oblookup (Vminibuffer_completion_table,
-                     XSTRING (tem)->data, XSTRING (tem)->size);
-      if (XTYPE (tem) != Lisp_Symbol)
-       tem = Qnil;
-      else if (!NILP (Vminibuffer_completion_predicate))
-       tem = call1 (Vminibuffer_completion_predicate, tem);
-      else
-       tem = Qt;
-    }
-  else
-    tem = call3 (Vminibuffer_completion_table,
-                Fbuffer_string (),
-                Vminibuffer_completion_predicate,
-                Qlambda);
-
+  tem = test_completion (Fbuffer_string ());
   if (NILP (tem))
-    { /* not an exact match */
+    {
+      /* not an exact match */
+      UNGCPRO;
       if (completedp)
        return 5;
       else if (auto_help)
@@ -1052,7 +1152,10 @@ do_completion ()
       return 6;
     }
   else if (completedp)
-    return 4;
+    {
+      UNGCPRO;
+      return 4;
+    }
   /* If the last exact completion and this one were the same,
      it means we've already given a "Complete but not unique"
      message and the user's hit TAB again, so now we give him help.  */
@@ -1063,9 +1166,10 @@ do_completion ()
       if (!NILP (Fequal (tem, last)))
        Fminibuffer_completion_help ();
     }
+  UNGCPRO;
   return 3;
 }
-  
+
 /* Like assoc but assumes KEY is a string, and ignores case if appropriate.  */
 
 Lisp_Object
@@ -1084,7 +1188,7 @@ assoc_for_completion (key, list)
       elt = Fcar (tail);
       if (!CONSP (elt)) continue;
       thiscar = Fcar (elt);
-      if (XTYPE (thiscar) != Lisp_String)
+      if (!STRINGP (thiscar))
        continue;
       if (completion_ignore_case)
        thiscar = Fupcase (thiscar);
@@ -1096,10 +1200,43 @@ assoc_for_completion (key, list)
 }
 
 DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0, "",
-  "Complete the minibuffer contents as far as possible.")
+  "Complete the minibuffer contents as far as possible.\n\
+Return nil if there is no valid completion, else t.\n\
+If no characters can be completed, display a list of possible completions.\n\
+If you repeat this command after it displayed such a list,\n\
+scroll the window of possible completions.")
   ()
 {
-  register int i = do_completion ();
+  register int i;
+  Lisp_Object window, tem;
+
+  /* If the previous command was not this, then mark the completion
+     buffer obsolete.  */
+  if (! EQ (last_command, this_command))
+    Vminibuf_scroll_window = Qnil;
+
+  window = Vminibuf_scroll_window;
+  /* If there's a fresh completion window with a live buffer,
+     and this command is repeated, scroll that window.  */
+  if (! NILP (window) && ! NILP (XWINDOW (window)->buffer)
+      && !NILP (XBUFFER (XWINDOW (window)->buffer)->name))
+    {
+      struct buffer *obuf = current_buffer;
+
+      Fset_buffer (XWINDOW (window)->buffer);
+      tem = Fpos_visible_in_window_p (make_number (ZV), window);
+      if (! NILP (tem))
+       /* If end is in view, scroll up to the beginning.  */
+       Fset_window_start (window, BEGV, Qnil);
+      else
+       /* Else scroll down one screen.  */
+       Fscroll_other_window (Qnil);
+
+      set_buffer_internal (obuf);
+      return Qnil;
+    }
+
+  i = do_completion ();
   switch (i)
     {
     case 0:
@@ -1116,22 +1253,49 @@ DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0,
 
   return Qt;
 }
+\f
+/* Subroutines of Fminibuffer_complete_and_exit.  */
+
+/* This one is called by internal_condition_case to do the real work.  */
+
+Lisp_Object
+complete_and_exit_1 ()
+{
+  return make_number (do_completion ());
+}
+
+/* This one is called by internal_condition_case if an error happens.
+   Pretend the current value is an exact match.  */
+
+Lisp_Object
+complete_and_exit_2 (ignore)
+     Lisp_Object ignore;
+{
+  return make_number (1);
+}
 
 DEFUN ("minibuffer-complete-and-exit", Fminibuffer_complete_and_exit,
         Sminibuffer_complete_and_exit, 0, 0, "",
-  "Complete the minibuffer contents, and maybe exit.\n\
-Exit if the name is valid with no completion needed.\n\
-If name was completed to a valid match,\n\
+  "If the minibuffer contents is a valid completion then exit.\n\
+Otherwise try to complete it.  If completion leads to a valid completion,\n\
 a repetition of this command will exit.")
   ()
 {
   register int i;
+  Lisp_Object val;
 
   /* Allow user to specify null string */
   if (BEGV == ZV)
     goto exit;
 
-  i = do_completion ();
+  if (!NILP (test_completion (Fbuffer_string ())))
+    goto exit;
+
+  /* Call do_completion, but ignore errors.  */
+  val = internal_condition_case (complete_and_exit_1, Qerror,
+                                complete_and_exit_2);
+
+  i = XFASTINT (val);
   switch (i)
     {
     case 1:
@@ -1159,13 +1323,14 @@ DEFUN ("minibuffer-complete-word", Fminibuffer_complete_word, Sminibuffer_comple
   0, 0, "",
   "Complete the minibuffer contents at most a single word.\n\
 After one word is completed as much as possible, a space or hyphen\n\
-is added, provided that matches some possible completion.")
+is added, provided that matches some possible completion.\n\
+Return nil if there is no valid completion, else t.")
   ()
 {
   Lisp_Object completion, tem;
   register int i;
   register unsigned char *completion_string;
-  struct gcpro gcpro1;
+  struct gcpro gcpro1, gcpro2;
 
   /* We keep calling Fbuffer_string rather than arrange for GC to
      hold onto a pointer to one of the strings thus made.  */
@@ -1203,6 +1368,7 @@ is added, provided that matches some possible completion.")
     int buffer_length, completion_length;
 
     tem = Fbuffer_string ();
+    GCPRO2 (completion, tem);
     /* If reading a file name,
        expand any $ENVVAR refs in the buffer and in TEM.  */
     if (EQ (Vminibuffer_completion_table, Qread_file_name_internal))
@@ -1234,6 +1400,7 @@ is added, provided that matches some possible completion.")
        del_range (1, i + 1);
        SET_PT (ZV);
       }
+    UNGCPRO;
   }
 #endif /* Rewritten code */
   i = ZV - BEGV;
@@ -1248,7 +1415,7 @@ is added, provided that matches some possible completion.")
                             Vminibuffer_completion_predicate);
       UNGCPRO;
 
-      if (XTYPE (tem) == Lisp_String)
+      if (STRINGP (tem))
        completion = tem;
       else
        {
@@ -1259,7 +1426,7 @@ is added, provided that matches some possible completion.")
                             Vminibuffer_completion_predicate);
          UNGCPRO;
 
-         if (XTYPE (tem) == Lisp_String)
+         if (STRINGP (tem))
            completion = tem;
        }
     }      
@@ -1294,17 +1461,25 @@ DEFUN ("display-completion-list", Fdisplay_completion_list, Sdisplay_completion_
        1, 1, 0,
   "Display the list of completions, COMPLETIONS, using `standard-output'.\n\
 Each element may be just a symbol or string\n\
-or may be a list of two strings to be printed as if concatenated.")
+or may be a list of two strings to be printed as if concatenated.\n\
+`standard-output' must be a buffer.\n\
+At the end, run the normal hook `completion-setup-hook'.\n\
+It can find the completion buffer in `standard-output'.")
   (completions)
      Lisp_Object completions;
 {
   register Lisp_Object tail, elt;
   register int i;
   int column = 0;
-  /* No GCPRO needed, since (when it matters) every variable
-     points to a non-string that is pointed to by COMPLETIONS.  */
+  struct gcpro gcpro1;
   struct buffer *old = current_buffer;
-  if (XTYPE (Vstandard_output) == Lisp_Buffer)
+  int first = 1;
+
+  /* Note that (when it matters) every variable
+     points to a non-string that is pointed to by COMPLETIONS.  */
+  GCPRO1 (completions);
+
+  if (BUFFERP (Vstandard_output))
     set_buffer_internal (XBUFFER (Vstandard_output));
 
   if (NILP (completions))
@@ -1315,14 +1490,49 @@ or may be a list of two strings to be printed as if concatenated.")
       write_string ("Possible completions are:", -1);
       for (tail = completions, i = 0; !NILP (tail); tail = Fcdr (tail), i++)
        {
-         /* this needs fixing for the case of long completions
-            and/or narrow windows */
-         /* Sadly, the window it will appear in is not known
-            until after the text has been made. */
-         if (i & 1)
+         Lisp_Object tem;
+         int length;
+
+         elt = Fcar (tail);
+         /* Compute the length of this element.  */
+         if (CONSP (elt))
+           {
+             tem = Fcar (elt);
+             CHECK_STRING (tem, 0);
+             length = XINT (XSTRING (tem)->size);
+
+             tem = Fcar (Fcdr (elt));
+             CHECK_STRING (tem, 0);
+             length += XINT (XSTRING (tem)->size);
+           }
+         else
            {
-             if (XTYPE (Vstandard_output) == Lisp_Buffer)
-               Findent_to (make_number (35), make_number (1));
+             CHECK_STRING (elt, 0);
+             length = XINT (XSTRING (elt)->size);
+           }
+
+         /* This does a bad job for narrower than usual windows.
+            Sadly, the window it will appear in is not known
+            until after the text has been made.  */
+
+         /* If the previous completion was very wide,
+            or we have two on this line already,
+            don't put another on the same line.  */
+         if (column > 33 || first
+             /* If this is really wide, don't put it second on a line.  */
+             || column > 0 && length > 45)
+           {
+             Fterpri (Qnil);
+             column = 0;
+           }
+         /* Otherwise advance to column 35.  */
+         else
+           {
+             if (BUFFERP (Vstandard_output))
+               {
+                 tem = Findent_to (make_number (35), make_number (2));
+                 column = XINT (tem);
+               }
              else
                {
                  do
@@ -1333,43 +1543,38 @@ or may be a list of two strings to be printed as if concatenated.")
                  while (column < 35);
                }
            }
-         else
-           {
-             Fterpri (Qnil);
-             column = 0;
-           }
-         elt = Fcar (tail);
+
+         /* Output this element and update COLUMN.  */
          if (CONSP (elt))
            {
-             if (XTYPE (Vstandard_output) != Lisp_Buffer)
-               {
-                 Lisp_Object tem;
-                 tem = Flength (Fcar (elt));
-                 column += XINT (tem);
-                 tem = Flength (Fcar (Fcdr (elt)));
-                 column += XINT (tem);
-               }
              Fprinc (Fcar (elt), Qnil);
              Fprinc (Fcar (Fcdr (elt)), Qnil);
            }
          else
+           Fprinc (elt, Qnil);
+
+         column += length;
+
+         /* If output is to a buffer, recompute COLUMN in a way
+            that takes account of character widths.  */
+         if (BUFFERP (Vstandard_output))
            {
-             if (XTYPE (Vstandard_output) != Lisp_Buffer)
-               {
-                 Lisp_Object tem;
-                 tem = Flength (elt);
-                 column += XINT (tem);
-               }
-             Fprinc (elt, Qnil);
+             tem = Fcurrent_column ();
+             column = XINT (tem);
            }
+
+         first = 0;
        }
     }
 
+  UNGCPRO;
+
+  if (BUFFERP (Vstandard_output))
+    set_buffer_internal (old);
+
   if (!NILP (Vrun_hooks))
     call1 (Vrun_hooks, intern ("completion-setup-hook"));
 
-  if (XTYPE (Vstandard_output) == Lisp_Buffer)
-    set_buffer_internal (old);
   return Qnil;
 }
 
@@ -1383,7 +1588,8 @@ DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_co
   message ("Making completion list...");
   completions = Fall_completions (Fbuffer_string (),
                                  Vminibuffer_completion_table,
-                                 Vminibuffer_completion_predicate);
+                                 Vminibuffer_completion_predicate,
+                                 Qt);
   echo_area_glyphs = 0;
 
   if (NILP (completions))
@@ -1402,7 +1608,7 @@ DEFUN ("self-insert-and-exit", Fself_insert_and_exit, Sself_insert_and_exit, 0,
   "Terminate minibuffer input.")
   ()
 {
-  if (XTYPE (last_command_char) == Lisp_Int)
+  if (INTEGERP (last_command_char))
     internal_self_insert (last_command_char, 0);
   else
     bitch_at_user ();
@@ -1424,6 +1630,23 @@ DEFUN ("minibuffer-depth", Fminibuffer_depth, Sminibuffer_depth, 0, 0, 0,
   return make_number (minibuf_level);
 }
 
+DEFUN ("minibuffer-prompt", Fminibuffer_prompt, Sminibuffer_prompt, 0, 0, 0,
+  "Return the prompt string of the currently-active minibuffer.\n\
+If no minibuffer is active, return nil.")
+  ()
+{
+  return Fcopy_sequence (minibuf_prompt);
+}
+
+DEFUN ("minibuffer-prompt-width", Fminibuffer_prompt_width,
+  Sminibuffer_prompt_width, 0, 0, 0,
+  "Return the display width of the minibuffer prompt.")
+  ()
+{
+  Lisp_Object width;
+  XSETFASTINT (width, minibuf_prompt_width);
+  return width;
+}
 \f
 init_minibuf_once ()
 {
@@ -1434,9 +1657,11 @@ init_minibuf_once ()
 syms_of_minibuf ()
 {
   minibuf_level = 0;
-  minibuf_prompt = 0;
-  minibuf_save_vector_size = 5;
-  minibuf_save_vector = (struct minibuf_save_data *) malloc (5 * sizeof (struct minibuf_save_data));
+  minibuf_prompt = Qnil;
+  staticpro (&minibuf_prompt);
+
+  minibuf_save_list = Qnil;
+  staticpro (&minibuf_save_list);
 
   Qread_file_name_internal = intern ("read-file-name-internal");
   staticpro (&Qread_file_name_internal);
@@ -1450,6 +1675,9 @@ syms_of_minibuf ()
   Qminibuffer_completion_predicate = intern ("minibuffer-completion-predicate");
   staticpro (&Qminibuffer_completion_predicate);
 
+  staticpro (&last_exact_completion);
+  last_exact_completion = Qnil;
+
   staticpro (&last_minibuf_string);
   last_minibuf_string = Qnil;
 
@@ -1462,10 +1690,17 @@ syms_of_minibuf ()
   Qminibuffer_setup_hook = intern ("minibuffer-setup-hook");
   staticpro (&Qminibuffer_setup_hook);
 
+  Qminibuffer_exit_hook = intern ("minibuffer-exit-hook");
+  staticpro (&Qminibuffer_exit_hook);
+
   DEFVAR_LISP ("minibuffer-setup-hook", &Vminibuffer_setup_hook, 
     "Normal hook run just after entry to minibuffer.");
   Vminibuffer_setup_hook = Qnil;
 
+  DEFVAR_LISP ("minibuffer-exit-hook", &Vminibuffer_exit_hook,
+    "Normal hook run just after exit from minibuffer.");
+  Vminibuffer_exit_hook = Qnil;
+
   DEFVAR_BOOL ("completion-auto-help", &auto_help,
     "*Non-nil means automatically provide help for invalid completion input.");
   auto_help = 1;
@@ -1512,7 +1747,7 @@ t means to return a list of all possible completions of STRING.\n\
 Each minibuffer output is added with\n\
   (set minibuffer-history-variable\n\
        (cons STRING (symbol-value minibuffer-history-variable)))");
-  XFASTINT (Vminibuffer_history_variable) = 0;
+  XSETFASTINT (Vminibuffer_history_variable, 0);
 
   DEFVAR_LISP ("minibuffer-history-position", &Vminibuffer_history_position,
     "Current position of redoing in the history list.");
@@ -1522,6 +1757,10 @@ Each minibuffer output is added with\n\
     "*Non-nil means entering the minibuffer raises the minibuffer's frame.");
   minibuffer_auto_raise = 0;
 
+  DEFVAR_LISP ("completion-regexp-list", &Vcompletion_regexp_list,
+    "List of regexps that should restrict possible completions.");
+  Vcompletion_regexp_list = Qnil;
+
   defsubr (&Sread_from_minibuffer);
   defsubr (&Seval_minibuffer);
   defsubr (&Sread_minibuffer);
@@ -1531,6 +1770,8 @@ Each minibuffer output is added with\n\
   defsubr (&Sread_buffer);
   defsubr (&Sread_no_blanks_input);
   defsubr (&Sminibuffer_depth);
+  defsubr (&Sminibuffer_prompt);
+  defsubr (&Sminibuffer_prompt_width);
 
   defsubr (&Stry_completion);
   defsubr (&Sall_completions);