(x_get_customization_string): Don't use value of strcpy.
[bpt/emacs.git] / src / minibuf.c
index 6369438..e941fd0 100644 (file)
@@ -1,11 +1,11 @@
 /* Minibuffer input and completion.
-   Copyright (C) 1985, 1986 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -23,7 +23,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "commands.h"
 #include "buffer.h"
 #include "dispextern.h"
-#include "screen.h"
+#include "frame.h"
 #include "window.h"
 #include "syntax.h"
 
@@ -41,6 +41,8 @@ struct minibuf_save_data
     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;
@@ -63,6 +65,16 @@ int enable_recursive_minibuffers;
 
 Lisp_Object Vminibuffer_help_form;
 
+/* Variable which is the history list to add minibuffer values to.  */
+
+Lisp_Object Vminibuffer_history_variable;
+
+/* Current position in the history list (adjusted by M-n and M-p).  */
+
+Lisp_Object Vminibuffer_history_position;
+
+Lisp_Object Qminibuffer_history;
+
 /* Nonzero means completion ignores case.  */
 
 int completion_ignore_case;
@@ -74,19 +86,6 @@ static Lisp_Object last_exact_completion;
 
 Lisp_Object Quser_variable_p;
 
-/* Width in columns of current minibuffer prompt.  */
-
-extern int minibuf_prompt_width;
-
-#ifdef MULTI_SCREEN
-
-/* When the global-minibuffer-screen is not used, this is the screen
-   where the minbuffer is active, and thus where certain windows
-   (completions, etc.) should appear. */
-struct screen *active_screen;
-
-extern Lisp_Object Vglobal_minibuffer_screen;
-#endif
 \f
 /* Actual minibuffer invocation. */
 
@@ -94,18 +93,28 @@ void read_minibuf_unwind ();
 Lisp_Object get_minibuffer ();
 Lisp_Object read_minibuf ();
 
+/* Read from the minibuffer using keymap MAP, initial contents INITIAL
+   (a string), putting point minus BACKUP_N chars from the end of INITIAL,
+   prompting with PROMPT (a string), using history list HISTVAR
+   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.  */
+
 Lisp_Object
-read_minibuf (map, initial, prompt, backup_n, expflag)
+read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
      Lisp_Object map;
      Lisp_Object initial;
      Lisp_Object prompt;
      Lisp_Object backup_n;
      int expflag;
+     Lisp_Object histvar;
+     Lisp_Object histpos;
 {
   register Lisp_Object val;
   int count = specpdl_ptr - specpdl;
+  Lisp_Object mini_frame;
   struct gcpro gcpro1, gcpro2;
-  Lisp_Object prev_screen = Qnil;
 
   if (XTYPE (prompt) != Lisp_String)
     prompt = build_string ("");
@@ -118,7 +127,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag)
       && minibuf_level > 0
       && (EQ (selected_window, minibuf_window)))
 #if 0
-         || selected_screen != XSCREEN (WINDOW_SCREEN (XWINDOW (minibuf_window)))
+         || selected_frame != XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)))
 #endif
     error ("Command attempted to use minibuffer while in minibuffer");
 
@@ -134,35 +143,74 @@ read_minibuf (map, initial, prompt, backup_n, expflag)
   /* >> 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);
 
   record_unwind_protect (Fset_window_configuration,
-                        Fcurrent_window_configuration ());
+                        Fcurrent_window_configuration (Qnil));
+
+  /* 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)));
+  if (XFRAME (mini_frame) != selected_frame)
+    record_unwind_protect (Fset_window_configuration,
+                          Fcurrent_window_configuration (mini_frame));
+#endif
 
   val = current_buffer->directory;
   Fset_buffer (get_minibuffer (minibuf_level));
-  current_buffer->directory = val;
+
+  /* The current buffer's default directory is usually the right thing
+     for our minibuffer here.  However, if you're typing a command at
+     a minibuffer-only frame when minibuf_level is zero, then buf IS
+     the current_buffer, so reset_buffer leaves buf's default
+     directory unchanged.  This is a bummer when you've just started
+     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)
+    current_buffer->directory = val;
+  else
+    {
+      Lisp_Object buf_list;
+
+      for (buf_list = Vbuffer_alist;
+          CONSP (buf_list);
+          buf_list = XCONS (buf_list)->cdr)
+       {
+         Lisp_Object other_buf = XCONS (XCONS (buf_list)->car)->cdr;
+
+         if (XTYPE (XBUFFER (other_buf)->directory) == Lisp_String)
+           {
+             current_buffer->directory = XBUFFER (other_buf)->directory;
+             break;
+           }
+       }
+    }
+
+#ifdef MULTI_FRAME
+  Fredirect_frame_focus (Fselected_frame (), mini_frame);
+#endif
   Fmake_local_variable (Qprint_escape_newlines);
   print_escape_newlines = 1;
 
+  record_unwind_protect (read_minibuf_unwind, Qnil);
+
   Vminibuf_scroll_window = selected_window;
   Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
-#ifdef MULTI_SCREEN
-  if (SCREENP (Vglobal_minibuffer_screen))
-    active_screen = selected_screen;
-#endif
   Fselect_window (minibuf_window);
   XFASTINT (XWINDOW (minibuf_window)->hscroll) = 0;
 
   Ferase_buffer ();
   minibuf_level++;
-  record_unwind_protect (read_minibuf_unwind, Qnil);
 
-  if (!NULL (initial))
+  if (!NILP (initial))
     {
       Finsert (1, &initial);
-      if (!NULL (backup_n) && XTYPE (backup_n) == Lisp_Int)
+      if (!NILP (backup_n) && XTYPE (backup_n) == Lisp_Int)
        Fforward_char (backup_n);
     }
 
@@ -172,41 +220,44 @@ read_minibuf (map, initial, prompt, backup_n, expflag)
 
   Vhelp_form = Vminibuffer_help_form;
   current_buffer->keymap = map;
+  Vminibuffer_history_position = histpos;
+  Vminibuffer_history_variable = histvar;
 
 /* ??? MCC did redraw_screen here if switching screens.  */
   recursive_edit_1 ();
 
   /* If cursor is on the minibuffer line,
      show the user we have exited by putting it in column 0.  */
-  if ((SCREEN_CURSOR_Y (selected_screen)
+  if ((FRAME_CURSOR_Y (selected_frame)
        >= XFASTINT (XWINDOW (minibuf_window)->top))
       && !noninteractive)
     {
-      SCREEN_CURSOR_X (selected_screen) = 0;
-      update_screen (selected_screen, 1, 1);
+      FRAME_CURSOR_X (selected_frame) = 0;
+      update_frame (selected_frame, 1, 1);
     }
 
   /* Make minibuffer contents into a string */
-  val = make_string (BEG_ADDR, Z - BEG);
+  val = make_buffer_string (1, Z);
   bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
-  unbind_to (count, Qnil);     /* The appropriate screen will get selected
-                                  from set-window-configuration. */
+
+  /* Add the value to the appropriate history list.  */
+  if (XTYPE (Vminibuffer_history_variable) == Lisp_Symbol
+      && ! EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
+    Fset (Vminibuffer_history_variable,
+         Fcons (val, Fsymbol_value (Vminibuffer_history_variable)));
+
+  unbind_to (count, Qnil);     /* The appropriate frame will get selected
+                                  in set-window-configuration.  */
 
   UNGCPRO;
 
   /* VAL is the string of minibuffer text.  */
-
   last_minibuf_string = val;
 
   /* If Lisp form desired instead of string, parse it */
   if (expflag)
     val = Fread (val);
 
-#ifdef MULTI_SCREEN
-  if (active_screen)
-    active_screen = (struct screen *) 0;
-#endif
-
   return val;
 }
 
@@ -224,20 +275,26 @@ get_minibuffer (depth)
 
   XFASTINT (num) = depth;
   tail = Fnthcdr (num, Vminibuffer_list);
-  if (NULL (tail))
+  if (NILP (tail))
     {
       tail = Fcons (Qnil, Qnil);
       Vminibuffer_list = nconc2 (Vminibuffer_list, tail);
     }
   buf = Fcar (tail);
-  if (NULL (buf) || NULL (XBUFFER (buf)->name))
+  if (NILP (buf) || NILP (XBUFFER (buf)->name))
     {
       sprintf (name, " *Minibuf-%d*", depth);
       buf = Fget_buffer_create (build_string (name));
+
+      /* Although the buffer's name starts with a space, undo should be
+        enabled in it.  */
+      Fbuffer_enable_undo (buf);
+
       XCONS (tail)->car = buf;
     }
   else
     reset_buffer (XBUFFER (buf));
+
   return buf;
 }
 
@@ -245,7 +302,8 @@ get_minibuffer (depth)
  and it restores the current window, buffer, etc. */
 
 void
-read_minibuf_unwind ()
+read_minibuf_unwind (data)
+     Lisp_Object data;
 {
   /* Erase the minibuffer we were using at this level.  */
   Fset_buffer (XWINDOW (minibuf_window)->buffer);
@@ -266,29 +324,57 @@ read_minibuf_unwind ()
   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;
 }
 \f
+
+/* This comment supplies the doc string for read-from-minibuffer, 
+   for make-docfile to see.  We cannot put this in the real DEFUN
+   due to limits in the Unix cpp.
+
 DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 5, 0,
   "Read a string from the minibuffer, prompting with string PROMPT.\n\
 If optional second arg INITIAL-CONTENTS is non-nil, it is a string\n\
   to be inserted into the minibuffer before reading input.\n\
+  If INITIAL-CONTENTS is (STRING . POSITION), the initial input\n\
+  is STRING, but point is placed POSITION characters into the string.\n\
 Third arg KEYMAP is a keymap to use whilst reading;\n\
   if omitted or nil, the default is `minibuffer-local-map'.\n\
 If fourth arg READ is non-nil, then interpret the result as a lisp object\n\
   and return that object:\n\
   in other words, do `(car (read-from-string INPUT-STRING))'\n\
-Fifth arg POSITION, if non-nil, is where to put point\n\
-  in the minibuffer after inserting INITIAL-CONTENTS.")
-  (prompt, initial_input, keymap, read, position)
-     Lisp_Object prompt, initial_input, keymap, read, position;
+Fifth arg HIST, if non-nil, specifies a history list\n\
+  and optionally the initial position in the list.\n\
+  It can be a symbol, which is the history list variable to use,\n\
+  or it can be a cons cell (HISTVAR . HISTPOS).\n\
+  In that case, HISTVAR is the history list variable to use,\n\
+  and HISTPOS is the initial position (the position in the list\n\
+  which INITIAL-CONTENTS corresponds to).\n\
+  Positions are counted starting from 1 at the beginning of the list."
+*/
+
+DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1, 5, 0,
+  0 /* See immediately above */)
+  (prompt, initial_input, keymap, read, hist)
+     Lisp_Object prompt, initial_input, keymap, read, hist;
 {
   int pos = 0;
+  Lisp_Object histvar, histpos, position;
+  position = Qnil;
 
   CHECK_STRING (prompt, 0);
-  if (!NULL (initial_input))
+  if (!NILP (initial_input))
     {
+      if (XTYPE (initial_input) == Lisp_Cons)
+       {
+         position = Fcdr (initial_input);
+         initial_input = Fcar (initial_input);
+       }
       CHECK_STRING (initial_input, 1);
-      if (!NULL (position))
+      if (!NILP (position))
        {
          CHECK_NUMBER (position, 0);
          /* Convert to distance from end of input.  */
@@ -296,12 +382,28 @@ Fifth arg POSITION, if non-nil, is where to put point\n\
        }
     }
 
-  if (NULL (keymap))
+  if (NILP (keymap))
     keymap = Vminibuffer_local_map;
   else
     keymap = get_keymap (keymap,2);
+
+  if (XTYPE (hist) == Lisp_Symbol)
+    {
+      histvar = hist;
+      histpos = Qnil;
+    }
+  else
+    {
+      histvar = Fcar_safe (hist);
+      histpos = Fcdr_safe (hist);
+    }
+  if (NILP (histvar))
+    histvar = Qminibuffer_history;
+  if (NILP (histpos))
+    XFASTINT (histpos) = 0;
+
   return read_minibuf (keymap, initial_input, prompt,
-                      pos, !NULL (read));
+                      make_number (pos), !NILP (read), histvar, histpos);
 }
 
 DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
@@ -312,9 +414,10 @@ is a string to insert in the minibuffer before reading.")
      Lisp_Object prompt, initial_contents;
 {
   CHECK_STRING (prompt, 0);
-  if (!NULL (initial_contents))
-    CHECK_STRING (initial_contents, 1)
-  return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, Qnil, 1);
+  if (!NILP (initial_contents))
+    CHECK_STRING (initial_contents, 1);
+  return read_minibuf (Vminibuffer_local_map, initial_contents,
+                      prompt, Qnil, 1, Qminibuffer_history, make_number (0));
 }
 
 DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0,
@@ -338,17 +441,18 @@ If non-nil second arg INITIAL-INPUT is a string to insert before reading.")
   return Fread_from_minibuffer (prompt, initial_input, Qnil, Qnil, Qnil);
 }
 
-DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 2, 1, 0,
+DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 2, 2, 0,
   "Args PROMPT and INIT, strings.  Read a string from the terminal, not allowing blanks.\n\
 Prompt with PROMPT, and provide INIT as an initial value of the input string.")
   (prompt, init)
      Lisp_Object prompt, init;
 {
   CHECK_STRING (prompt, 0);
-  if (! NULL (init))
+  if (! NILP (init))
     CHECK_STRING (init, 1);
 
-  return read_minibuf (Vminibuffer_local_ns_map, init, prompt, Qnil, 0);
+  return read_minibuf (Vminibuffer_local_ns_map, init, prompt, Qnil, 0,
+                      Qminibuffer_history, make_number (0));
 }
 
 DEFUN ("read-command", Fread_command, Sread_command, 1, 1, 0,
@@ -399,7 +503,7 @@ If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are a
 
   if (XTYPE (def) == Lisp_Buffer)
     def = XBUFFER (def)->name;
-  if (!NULL (def))
+  if (!NILP (def))
     {
       args[0] = build_string ("%s(default %s) ");
       args[1] = prompt;
@@ -439,7 +543,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
   Lisp_Object bestmatch, tail, elt, eltstring;
   int bestmatchsize;
   int compare, matchsize;
-  int list = CONSP (alist) || NULL (alist);
+  int list = CONSP (alist) || NILP (alist);
   int index, obsize;
   int matchcount = 0;
   Lisp_Object bucket, zero, end, tem;
@@ -469,7 +573,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
 
       if (list)
        {
-         if (NULL (tail))
+         if (NILP (tail))
            break;
          elt = Fcar (tail);
          eltstring = Fcar (elt);
@@ -506,7 +610,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
          /* Ignore this element if there is a predicate
             and the predicate doesn't like it. */
 
-         if (!NULL (pred))
+         if (!NILP (pred))
            {
              if (EQ (pred, Qcommandp))
                tem = Fcommandp (elt);
@@ -516,13 +620,13 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
                  tem = call1 (pred, elt);
                  UNGCPRO;
                }
-             if (NULL (tem)) continue;
+             if (NILP (tem)) continue;
            }
 
          /* Update computation of how much all possible completions match */
 
          matchcount++;
-         if (NULL (bestmatch))
+         if (NILP (bestmatch))
            bestmatch = eltstring, bestmatchsize = XSTRING (eltstring)->size;
          else
            {
@@ -561,7 +665,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
        }
     }
 
-  if (NULL (bestmatch))
+  if (NILP (bestmatch))
     return Qnil;               /* No completions found */
   /* If we are ignoring case, and there is no exact match,
      and no additional text was supplied,
@@ -628,7 +732,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
 {
   Lisp_Object tail, elt, eltstring;
   Lisp_Object allmatches;
-  int list = CONSP (alist) || NULL (alist);
+  int list = CONSP (alist) || NILP (alist);
   int index, obsize;
   Lisp_Object bucket, tem;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -658,7 +762,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
 
       if (list)
        {
-         if (NULL (tail))
+         if (NILP (tail))
            break;
          elt = Fcar (tail);
          eltstring = Fcar (elt);
@@ -696,7 +800,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
          /* Ignore this element if there is a predicate
             and the predicate doesn't like it. */
 
-         if (!NULL (pred))
+         if (!NILP (pred))
            {
              if (EQ (pred, Qcommandp))
                tem = Fcommandp (elt);
@@ -706,7 +810,7 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
                  tem = call1 (pred, elt);
                  UNGCPRO;
                }
-             if (NULL (tem)) continue;
+             if (NILP (tem)) continue;
            }
          /* Ok => put it on the list. */
          allmatches = Fcons (eltstring, allmatches);
@@ -720,9 +824,13 @@ Lisp_Object Vminibuffer_completion_table, Qminibuffer_completion_table;
 Lisp_Object Vminibuffer_completion_predicate, Qminibuffer_completion_predicate;
 Lisp_Object Vminibuffer_completion_confirm, Qminibuffer_completion_confirm;
 
+/* This comment supplies the doc string for completing-read,
+   for make-docfile to see.  We cannot put this in the real DEFUN
+   due to limits in the Unix cpp.
+
 DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
   "Read a string in the minibuffer, with completion.\n\
-Args are PROMPT, TABLE, PREDICATE, REQUIRE-MATCH and INITIAL-INPUT.\n\
+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\
@@ -731,25 +839,70 @@ 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\
  If it is also not t, Return does not exit if it does non-null completion.\n\
 If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
-Case is ignored if ambient value of `completion-ignore-case' is non-nil.\n\
-If BACKUP-N is specified, point should be placed that many spaces from\n\
-the end of the buffer.  This is useful when providing default values,\n\
-because you can put point before the last component of a filename or any\n\
-other component that is likely to be deleted.")
-  (prompt, table, pred, require_match, init, backup_n)
-     Lisp_Object prompt, table, pred, require_match, init, backup_n;
+  If it is (STRING . POSITION), the initial input\n\
+  is STRING, but point is placed POSITION characters into the string.\n\
+HIST, if non-nil, specifies a history list\n\
+  and optionally the initial position in the list.\n\
+  It can be a symbol, which is the history list variable to use,\n\
+  or it can be a cons cell (HISTVAR . HISTPOS).\n\
+  In that case, HISTVAR is the history list variable to use,\n\
+  and HISTPOS is the initial position (the position in the list\n\
+  which INITIAL-CONTENTS corresponds to).\n\
+  Positions are counted starting from 1 at the beginning of the list.\n\
+Completion ignores case if the ambient value of\n\
+  `completion-ignore-case' is non-nil."
+*/
+DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
+  0 /* See immediately above */)
+  (prompt, table, pred, require_match, init, hist)
+     Lisp_Object prompt, table, pred, require_match, init, hist;
 {
-  Lisp_Object val;
+  Lisp_Object val, histvar, histpos, position;
+  int pos = 0;
   int count = specpdl_ptr - specpdl;
   specbind (Qminibuffer_completion_table, table);
   specbind (Qminibuffer_completion_predicate, pred);
   specbind (Qminibuffer_completion_confirm,
            EQ (require_match, Qt) ? Qnil : Qt);
   last_exact_completion = Qnil;
-  val = read_minibuf (NULL (require_match)
+
+  position = Qnil;
+  if (!NILP (init))
+    {
+      if (XTYPE (init) == Lisp_Cons)
+       {
+         position = Fcdr (init);
+         init = Fcar (init);
+       }
+      CHECK_STRING (init, 0);
+      if (!NILP (position))
+       {
+         CHECK_NUMBER (position, 0);
+         /* Convert to distance from end of input.  */
+         pos = XINT (position) - XSTRING (init)->size;
+       }
+    }
+
+  if (XTYPE (hist) == Lisp_Symbol)
+    {
+      histvar = hist;
+      histpos = Qnil;
+    }
+  else
+    {
+      histvar = Fcar_safe (hist);
+      histpos = Fcdr_safe (hist);
+    }
+  if (NILP (histvar))
+    histvar = Qminibuffer_history;
+  if (NILP (histpos))
+    XFASTINT (histpos) = 0;
+
+  val = read_minibuf (NILP (require_match)
                      ? Vminibuffer_local_completion_map
                      : Vminibuffer_local_must_match_map,
-                     init, prompt, backup_n, 0);
+                     init, prompt, make_number (pos), 0,
+                     histvar, histpos);
   return unbind_to (count, val);
 }
 \f
@@ -762,17 +915,12 @@ other component that is likely to be deleted.")
 temp_echo_area_glyphs (m)
      char *m;
 {
-  /* It's not very modular to do things this way, but then it seems
-     to me that the whole echo_area_glyphs thing is a hack anyway.  */
-  extern char *previous_echo_glyphs;
-
   int osize = ZV;
   Lisp_Object oinhibit;
   oinhibit = Vinhibit_quit;
 
-  /* Clear out any old echo-area message to make way for our new
-     thing.  */
-  echo_area_glyphs = previous_echo_glyphs = 0;
+  /* Clear out any old echo-area message to make way for our new thing.  */
+  message (0);
 
   SET_PT (osize);
   insert_string (m);
@@ -780,10 +928,10 @@ temp_echo_area_glyphs (m)
   Vinhibit_quit = Qt;
   Fsit_for (make_number (2), Qnil, Qnil);
   del_range (point, ZV);
-  if (!NULL (Vquit_flag))
+  if (!NILP (Vquit_flag))
     {
       Vquit_flag = Qnil;
-      unread_command_char = Ctl ('g');
+      unread_command_events = Fcons (make_number (Ctl ('g')), Qnil);
     }
   Vinhibit_quit = oinhibit;
 }
@@ -811,7 +959,7 @@ do_completion ()
   last = last_exact_completion;
   last_exact_completion = Qnil;
 
-  if (NULL (completion))
+  if (NILP (completion))
     {
       bitch_at_user ();
       temp_echo_area_glyphs (" [No match]");
@@ -823,7 +971,7 @@ do_completion ()
 
   /* compiler bug */
   tem = Fstring_equal (completion, Fbuffer_string());
-  if (completedp = NULL (tem))
+  if (completedp = NILP (tem))
     {
       Ferase_buffer ();                /* Some completion happened */
       Finsert (1, &completion);
@@ -831,7 +979,7 @@ do_completion ()
 
   /* It did find a match.  Do we match some possibility exactly now? */
   if (CONSP (Vminibuffer_completion_table)
-      || NULL (Vminibuffer_completion_table))
+      || NILP (Vminibuffer_completion_table))
     tem = assoc_for_completion (Fbuffer_string (),
                                Vminibuffer_completion_table);
   else if (XTYPE (Vminibuffer_completion_table) == Lisp_Vector)
@@ -845,7 +993,7 @@ do_completion ()
                      XSTRING (tem)->data, XSTRING (tem)->size);
       if (XTYPE (tem) != Lisp_Symbol)
        tem = Qnil;
-      else if (!NULL (Vminibuffer_completion_predicate))
+      else if (!NILP (Vminibuffer_completion_predicate))
        tem = call1 (Vminibuffer_completion_predicate, tem);
       else
        tem = Qt;
@@ -856,7 +1004,7 @@ do_completion ()
                 Vminibuffer_completion_predicate,
                 Qlambda);
 
-  if (NULL (tem))
+  if (NILP (tem))
     { /* not an exact match */
       if (completedp)
        return 5;
@@ -872,10 +1020,10 @@ do_completion ()
      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.  */
   last_exact_completion = completion;
-  if (!NULL (last))
+  if (!NILP (last))
     {
       tem = Fbuffer_string ();
-      if (!NULL (Fequal (tem, last)))
+      if (!NILP (Fequal (tem, last)))
        Fminibuffer_completion_help ();
     }
   return 3;
@@ -893,7 +1041,7 @@ assoc_for_completion (key, list)
   if (completion_ignore_case)
     key = Fupcase (key);
 
-  for (tail = list; !NULL (tail); tail = Fcdr (tail))
+  for (tail = list; !NILP (tail); tail = Fcdr (tail))
     {
       register Lisp_Object elt, tem, thiscar;
       elt = Fcar (tail);
@@ -904,7 +1052,7 @@ assoc_for_completion (key, list)
       if (completion_ignore_case)
        thiscar = Fupcase (thiscar);
       tem = Fequal (thiscar, key);
-      if (!NULL (tem)) return elt;
+      if (!NILP (tem)) return elt;
       QUIT;
     }
   return Qnil;
@@ -954,7 +1102,7 @@ a repetition of this command will exit.")
       goto exit;
 
     case 4:
-      if (!NULL (Vminibuffer_completion_confirm))
+      if (!NILP (Vminibuffer_completion_confirm))
        {
          temp_echo_area_glyphs (" [Confirm]");
          return Qnil;
@@ -987,7 +1135,7 @@ is added, provided that matches some possible completion.")
   completion = Ftry_completion (Fbuffer_string (),
                                Vminibuffer_completion_table,
                                Vminibuffer_completion_predicate);
-  if (NULL (completion))
+  if (NILP (completion))
     {
       bitch_at_user ();
       temp_echo_area_glyphs (" [No match]");
@@ -1085,7 +1233,7 @@ is added, provided that matches some possible completion.")
 \f
 DEFUN ("display-completion-list", Fdisplay_completion_list, Sdisplay_completion_list,
        1, 1, 0,
-  "Display in a buffer the list of completions, COMPLETIONS.\n\
+  "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.")
   (completions)
@@ -1093,38 +1241,76 @@ or may be a list of two strings to be printed as if concatenated.")
 {
   register Lisp_Object tail, elt;
   register int i;
-  struct buffer *old = current_buffer;
+  int column = 0;
   /* No GCPRO needed, since (when it matters) every variable
      points to a non-string that is pointed to by COMPLETIONS.  */
+  struct buffer *old = current_buffer;
+  if (XTYPE (Vstandard_output) == Lisp_Buffer)
+    set_buffer_internal (XBUFFER (Vstandard_output));
 
-  set_buffer_internal (XBUFFER (Vstandard_output));
-
-  if (NULL (completions))
-    insert_string ("There are no possible completions of what you have typed.");
+  if (NILP (completions))
+    write_string ("There are no possible completions of what you have typed.",
+                 -1);
   else
     {
-      insert_string ("Possible completions are:");
-      for (tail = completions, i = 0; !NULL (tail); tail = Fcdr (tail), i++)
+      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)
-           Findent_to (make_number (35), make_number (1));
+           {
+             if (XTYPE (Vstandard_output) == Lisp_Buffer)
+               Findent_to (make_number (35), make_number (1));
+             else
+               {
+                 do
+                   {
+                     write_string (" ", -1);
+                     column++;
+                   }
+                 while (column < 35);
+               }
+           }
          else
-           Fterpri (Qnil);
+           {
+             Fterpri (Qnil);
+             column = 0;
+           }
          elt = Fcar (tail);
          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);
+           {
+             if (XTYPE (Vstandard_output) != Lisp_Buffer)
+               {
+                 Lisp_Object tem;
+                 tem = Flength (elt);
+                 column += XINT (tem);
+               }
+             Fprinc (elt, Qnil);
+           }
        }
     }
-  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;
 }
 
@@ -1141,7 +1327,7 @@ DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_co
                                  Vminibuffer_completion_predicate);
   echo_area_glyphs = 0;
 
-  if (NULL (completions))
+  if (NILP (completions))
     {
       bitch_at_user ();
       temp_echo_area_glyphs (" [No completions]");
@@ -1208,7 +1394,8 @@ syms_of_minibuf ()
   Quser_variable_p = intern ("user-variable-p");
   staticpro (&Quser_variable_p);
 
-
+  Qminibuffer_history = intern ("minibuffer-history");
+  staticpro (&Qminibuffer_history);
 
   DEFVAR_BOOL ("completion-auto-help", &auto_help,
     "*Non-nil means automatically provide help for invalid completion input.");
@@ -1251,6 +1438,17 @@ t means to return a list of all possible completions of STRING.\n\
     "Value that `help-form' takes on inside the minibuffer.");
   Vminibuffer_help_form = Qnil;
 
+  DEFVAR_LISP ("minibuffer-history-variable", &Vminibuffer_history_variable,
+    "History list symbol to add minibuffer values to.\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;
+
+  DEFVAR_LISP ("minibuffer-history-position", &Vminibuffer_history_position,
+    "Current position of redoing in the history list.");
+  Vminibuffer_history_position = Qnil;
+
   defsubr (&Sread_from_minibuffer);
   defsubr (&Seval_minibuffer);
   defsubr (&Sread_minibuffer);