]> code.delx.au - gnu-emacs/blobdiff - src/minibuf.c
Remove #definition of HAVE_CLOSEDIR; autoconf figures this out.
[gnu-emacs] / src / minibuf.c
index 9f96f15d5df7322c77bf5fcf9f73da4e93db0f53..f7043d8afa618a795e1ab219e7b72422e8ba1e5c 100644 (file)
@@ -1,5 +1,5 @@
 /* Minibuffer input and completion.
-   Copyright (C) 1985, 1986, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -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;
@@ -81,17 +93,27 @@ 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_screen = WINDOW_SCREEN (XWINDOW (minibuf_window));
+  Lisp_Object mini_frame;
   struct gcpro gcpro1, gcpro2;
 
   if (XTYPE (prompt) != Lisp_String)
@@ -105,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");
 
@@ -121,43 +143,61 @@ 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 (Qnil));
 
-  /* If the minibuffer window is on a different screen, save that
-     screen's configuration too.  */
-  if (XSCREEN (mini_screen) != selected_screen)
-    {
-      record_unwind_protect (Fset_window_configuration,
-                            Fcurrent_window_configuration (mini_screen));
-    }
+  /* 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;
-  Fmake_local_variable (Qprint_escape_newlines);
-  print_escape_newlines = 1;
 
-#ifdef MULTI_SCREEN
-  /* If the minibuffer window is on another screen, shift this screen's
-     focus to that window, and arrange to put it back later.  */
-  if (XSCREEN (WINDOW_SCREEN (XWINDOW (minibuf_window)))
-      != selected_screen)
+  /* 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
     {
-      record_unwind_protect (read_minibuf_unwind,
-                            Fcons (Fselected_screen (),
-                                   SCREEN_FOCUS_SCREEN (selected_screen)));
+      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;
 
-      Fredirect_screen_focus (Fselected_screen (), mini_screen);
+         if (XTYPE (XBUFFER (other_buf)->directory) == Lisp_String)
+           {
+             current_buffer->directory = XBUFFER (other_buf)->directory;
+             break;
+           }
+       }
     }
-  else
-    record_unwind_protect (read_minibuf_unwind, Qnil);
-#else
-  record_unwind_protect (read_minibuf_unwind, Qnil);
+
+#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 ());
@@ -180,30 +220,38 @@ 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_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
+
+  /* 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 */
@@ -237,10 +285,16 @@ get_minibuffer (depth)
     {
       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;
 }
 
@@ -270,33 +324,55 @@ read_minibuf_unwind (data)
   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;
-
-#ifdef MULTI_SCREEN
-  /* Redirect the focus of the screen that called the minibuffer.  */
-  if (CONSP (data))
-    Fredirect_screen_focus (XCONS (data)->car, XCONS (data)->cdr);
-#endif
+  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 (!NILP (initial_input))
     {
+      if (XTYPE (initial_input) == Lisp_Cons)
+       {
+         position = Fcdr (initial_input);
+         initial_input = Fcar (initial_input);
+       }
       CHECK_STRING (initial_input, 1);
       if (!NILP (position))
        {
@@ -310,8 +386,24 @@ Fifth arg POSITION, if non-nil, is where to put point\n\
     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, !NILP (read));
+                      make_number (pos), !NILP (read), histvar, histpos);
 }
 
 DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
@@ -324,7 +416,8 @@ is a string to insert in the minibuffer before reading.")
   CHECK_STRING (prompt, 0);
   if (!NILP (initial_contents))
     CHECK_STRING (initial_contents, 1)
-  return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, Qnil, 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,
@@ -358,7 +451,8 @@ Prompt with PROMPT, and provide INIT as an initial value of the input string.")
   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,
@@ -730,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: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT, BACKUP-N.\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\
@@ -741,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;
+
+  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
@@ -772,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);
@@ -793,7 +931,7 @@ temp_echo_area_glyphs (m)
   if (!NILP (Vquit_flag))
     {
       Vquit_flag = Qnil;
-      unread_command_char = Ctl ('g');
+      unread_command_events = Fcons (make_number (Ctl ('g')), Qnil);
     }
   Vinhibit_quit = oinhibit;
 }
@@ -1095,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)
@@ -1103,17 +1241,18 @@ 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.  */
-
-  set_buffer_internal (XBUFFER (Vstandard_output));
+  struct buffer *old = current_buffer;
+  if (XTYPE (Vstandard_output) == Lisp_Buffer)
+    set_buffer_internal (XBUFFER (Vstandard_output));
 
   if (NILP (completions))
-    insert_string ("There are no possible completions of what you have typed.");
+    write_string ("There are no possible completions of what you have typed.", -1);
   else
     {
-      insert_string ("Possible completions are:");
+      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
@@ -1121,20 +1260,53 @@ or may be a list of two strings to be printed as if concatenated.")
          /* 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 (XTYPE (Vstandard_output) == Lisp_Buffer)
+    set_buffer_internal (old);
   return Qnil;
 }
 
@@ -1218,7 +1390,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.");
@@ -1261,6 +1434,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);