(LD_SWITCH_SYSTEM): Undo previous change.
[bpt/emacs.git] / src / minibuf.c
index 185995e..c3209e6 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.
 
@@ -18,7 +18,7 @@ along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
@@ -29,6 +29,8 @@ 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.
@@ -54,7 +56,7 @@ int minibuf_level;
 /* Nonzero means display completion help for invalid input */
 int auto_help;
 
-/* Fread_minibuffer leaves the input, as a string, here */
+/* Fread_minibuffer leaves the input here as a string. */
 Lisp_Object last_minibuf_string;
 
 /* Nonzero means let functions called when within a minibuffer 
@@ -75,17 +77,27 @@ Lisp_Object Vminibuffer_history_position;
 
 Lisp_Object Qminibuffer_history;
 
+Lisp_Object Qread_file_name_internal;
+
+/* Normal hook for entry to minibuffer.  */
+
+Lisp_Object Qminibuffer_setup_hook, Vminibuffer_setup_hook;
+
 /* Nonzero means completion ignores case.  */
 
 int completion_ignore_case;
 
+/* Nonzero means raise the minibuffer frame when the minibuffer
+   is entered.  */
+
+int minibuffer_auto_raise;
+
 /* If last completion attempt reported "Complete but not unique"
    then this is the string completed then; otherwise this is nil.  */
 
 static Lisp_Object last_exact_completion;
 
 Lisp_Object Quser_variable_p;
-
 \f
 /* Actual minibuffer invocation. */
 
@@ -99,21 +111,25 @@ 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 non-nil, 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.  */
 
 Lisp_Object
 read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
      Lisp_Object map;
      Lisp_Object initial;
      Lisp_Object prompt;
-     int backup_n;
+     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 = WINDOW_FRAME (XWINDOW (minibuf_window));
+  Lisp_Object mini_frame;
   struct gcpro gcpro1, gcpro2;
 
   if (XTYPE (prompt) != Lisp_String)
@@ -153,35 +169,58 @@ 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)));
   if (XFRAME (mini_frame) != selected_frame)
-    {
-      record_unwind_protect (Fset_window_configuration,
-                            Fcurrent_window_configuration (mini_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
 
   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_FRAME
-  /* If the minibuffer window is on another frame, shift this frame's
-     focus to that window, and arrange to put it back later.  */
-  if (XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)))
-      != selected_frame)
+  /* 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_frame (),
-                                   FRAME_FOCUS_FRAME (selected_frame)));
+      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_frame_focus (Fselected_frame (), mini_frame);
+         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 ());
@@ -207,6 +246,13 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   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)
+      && !NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qminibuffer_setup_hook);
+
 /* ??? MCC did redraw_screen here if switching screens.  */
   recursive_edit_1 ();
 
@@ -224,24 +270,46 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   val = make_buffer_string (1, Z);
   bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
 
+  /* 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
-      && XSYMBOL (Vminibuffer_history_variable)->value != Qunbound)
-    Fset (Vminibuffer_history_variable,
-         Fcons (val, Fsymbol_value (Vminibuffer_history_variable)));
+      && ! EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
+    {
+      /* If the caller wanted to save the value read on a history list,
+        then do so if the value is not already the front of the list.  */
+      Lisp_Object histval;
+      histval = Fsymbol_value (Vminibuffer_history_variable);
+
+      /* The value of the history variable must be a cons or nil.  Other
+        values are unacceptable.  We silently ignore these values.  */
+      if (NILP (histval)
+         || (CONSP (histval)
+             && NILP (Fequal (last_minibuf_string, Fcar (histval)))))
+       Fset (Vminibuffer_history_variable,
+             Fcons (last_minibuf_string, histval));
+    }
+
+  /* If Lisp form desired instead of string, parse it. */
+  if (expflag)
+    {
+      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);
+    }
 
   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);
-
   return val;
 }
 
@@ -254,7 +322,7 @@ get_minibuffer (depth)
      int depth;
 {
   Lisp_Object tail, num, buf;
-  char name[14];
+  char name[24];
   extern Lisp_Object nconc2 ();
 
   XFASTINT (num) = depth;
@@ -269,10 +337,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;
 }
 
@@ -306,12 +380,6 @@ read_minibuf_unwind (data)
     = minibuf_save_vector[minibuf_level].history_position;
   Vminibuffer_history_variable
     = minibuf_save_vector[minibuf_level].history_variable;
-
-#ifdef MULTI_FRAME
-  /* Redirect the focus of the frame that called the minibuffer.  */
-  if (CONSP (data))
-    Fredirect_frame_focus (XCONS (data)->car, XCONS (data)->cdr);
-#endif
 }
 \f
 
@@ -342,27 +410,27 @@ Fifth arg HIST, if non-nil, specifies a history list\n\
 
 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;
+  (prompt, initial_contents, keymap, read, hist)
+     Lisp_Object prompt, initial_contents, keymap, read, hist;
 {
   int pos = 0;
   Lisp_Object histvar, histpos, position;
   position = Qnil;
 
   CHECK_STRING (prompt, 0);
-  if (!NILP (initial_input))
+  if (!NILP (initial_contents))
     {
-      if (XTYPE (initial_input) == Lisp_Cons)
+      if (XTYPE (initial_contents) == Lisp_Cons)
        {
-         position = Fcdr (initial_input);
-         initial_input = Fcar (initial_input);
+         position = Fcdr (initial_contents);
+         initial_contents = Fcar (initial_contents);
        }
-      CHECK_STRING (initial_input, 1);
+      CHECK_STRING (initial_contents, 1);
       if (!NILP (position))
        {
          CHECK_NUMBER (position, 0);
          /* Convert to distance from end of input.  */
-         pos = XINT (position) - 1 - XSTRING (initial_input)->size;
+         pos = XINT (position) - 1 - XSTRING (initial_contents)->size;
        }
     }
 
@@ -386,7 +454,7 @@ DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1,
   if (NILP (histpos))
     XFASTINT (histpos) = 0;
 
-  return read_minibuf (keymap, initial_input, prompt,
+  return read_minibuf (keymap, initial_contents, prompt,
                       make_number (pos), !NILP (read), histvar, histpos);
 }
 
@@ -399,7 +467,7 @@ is a string to insert in the minibuffer before reading.")
 {
   CHECK_STRING (prompt, 0);
   if (!NILP (initial_contents))
-    CHECK_STRING (initial_contents, 1)
+    CHECK_STRING (initial_contents, 1);
   return read_minibuf (Vminibuffer_local_map, initial_contents,
                       prompt, Qnil, 1, Qminibuffer_history, make_number (0));
 }
@@ -425,7 +493,7 @@ 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, 2, 0,
+DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 1, 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)
@@ -774,11 +842,14 @@ 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 &&
-         XSTRING (eltstring)->data[0] != ' ' &&
-         0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
-                   XSTRING (string)->size))
+      if (XTYPE (eltstring) == Lisp_String
+         && XSTRING (string)->size <= XSTRING (eltstring)->size
+         /* Reject alternatives that start with space
+            unless the input starts with space.  */
+         && ((XSTRING (string)->size > 0 && XSTRING (string)->data[0] == ' ')
+             || XSTRING (eltstring)->data[0] != ' ')
+         && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+                      XSTRING (string)->size))
        {
          /* Yes. */
          /* Ignore this element if there is a predicate
@@ -899,17 +970,12 @@ DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
 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);
@@ -920,7 +986,7 @@ temp_echo_area_glyphs (m)
   if (!NILP (Vquit_flag))
     {
       Vquit_flag = Qnil;
-      unread_command_char = Ctl ('g');
+      unread_command_events = Fcons (make_number (quit_char), Qnil);
     }
   Vinhibit_quit = oinhibit;
 }
@@ -1048,7 +1114,8 @@ 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.")
   ()
 {
   register int i = do_completion ();
@@ -1111,15 +1178,17 @@ 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;
-  /* We keep calling Fbuffer_string
-     rather than arrange for GC to hold onto a pointer to
-     one of the strings thus made.  */
+  struct gcpro gcpro1;
+
+  /* We keep calling Fbuffer_string rather than arrange for GC to
+     hold onto a pointer to one of the strings thus made.  */
 
   completion = Ftry_completion (Fbuffer_string (),
                                Vminibuffer_completion_table,
@@ -1133,7 +1202,7 @@ is added, provided that matches some possible completion.")
   if (EQ (completion, Qt))
     return Qnil;
 
-#if 0 /* How the below code used to look, for reference */
+#if 0 /* How the below code used to look, for reference. */
   tem = Fbuffer_string ();
   b = XSTRING (tem)->data;
   i = ZV - 1 - XSTRING (completion)->size;
@@ -1154,6 +1223,19 @@ is added, provided that matches some possible completion.")
     int buffer_length, completion_length;
 
     tem = Fbuffer_string ();
+    /* If reading a file name,
+       expand any $ENVVAR refs in the buffer and in TEM.  */
+    if (EQ (Vminibuffer_completion_table, Qread_file_name_internal))
+      {
+       Lisp_Object substituted;
+       substituted = Fsubstitute_in_file_name (tem);
+       if (! EQ (substituted, tem))
+         {
+           tem = substituted;
+           Ferase_buffer ();
+           insert_from_string (tem, 0, XSTRING (tem)->size, 0);
+         }
+      }
     buffer_string = XSTRING (tem)->data;
     completion_string = XSTRING (completion)->data;
     buffer_length = XSTRING (tem)->size; /* ie ZV - BEGV */
@@ -1177,19 +1259,26 @@ is added, provided that matches some possible completion.")
   i = ZV - BEGV;
 
   /* If completion finds next char not unique,
-     consider adding a space or a hyphen */
+     consider adding a space or a hyphen. */
   if (i == XSTRING (completion)->size)
     {
+      GCPRO1 (completion);
       tem = Ftry_completion (concat2 (Fbuffer_string (), build_string (" ")),
                             Vminibuffer_completion_table,
                             Vminibuffer_completion_predicate);
+      UNGCPRO;
+
       if (XTYPE (tem) == Lisp_String)
        completion = tem;
       else
        {
-         tem = Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
-                                Vminibuffer_completion_table,
-                                Vminibuffer_completion_predicate);
+         GCPRO1 (completion);
+         tem =
+           Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
+                            Vminibuffer_completion_table,
+                            Vminibuffer_completion_predicate);
+         UNGCPRO;
+
          if (XTYPE (tem) == Lisp_String)
            completion = tem;
        }
@@ -1197,6 +1286,7 @@ is added, provided that matches some possible completion.")
 
   /* Now find first word-break in the stuff found by completion.
      i gets index in string of where to stop completing.  */
+
   completion_string = XSTRING (completion)->data;
 
   for (; i < XSTRING (completion)->size; i++)
@@ -1216,7 +1306,7 @@ is added, provided that matches some possible completion.")
   /* Otherwise insert in minibuffer the chars we got */
 
   Ferase_buffer ();
-  insert_from_string (completion, 0, i);
+  insert_from_string (completion, 0, i, 1);
   return Qt;
 }
 \f
@@ -1224,7 +1314,10 @@ 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;
 {
@@ -1238,7 +1331,8 @@ or may be a list of two strings to be printed as if concatenated.")
     set_buffer_internal (XBUFFER (Vstandard_output));
 
   if (NILP (completions))
-    write_string ("There are no possible completions of what you have typed.", -1);
+    write_string ("There are no possible completions of what you have typed.",
+                 -1);
   else
     {
       write_string ("Possible completions are:", -1);
@@ -1286,7 +1380,7 @@ or may be a list of two strings to be printed as if concatenated.")
              if (XTYPE (Vstandard_output) != Lisp_Buffer)
                {
                  Lisp_Object tem;
-                 tem = Flength (elt, Qt);
+                 tem = Flength (elt);
                  column += XINT (tem);
                }
              Fprinc (elt, Qnil);
@@ -1296,6 +1390,10 @@ or may be a list of two strings to be printed as if concatenated.")
 
   if (XTYPE (Vstandard_output) == Lisp_Buffer)
     set_buffer_internal (old);
+
+  if (!NILP (Vrun_hooks))
+    call1 (Vrun_hooks, intern ("completion-setup-hook"));
+
   return Qnil;
 }
 
@@ -1364,6 +1462,9 @@ syms_of_minibuf ()
   minibuf_save_vector_size = 5;
   minibuf_save_vector = (struct minibuf_save_data *) malloc (5 * sizeof (struct minibuf_save_data));
 
+  Qread_file_name_internal = intern ("read-file-name-internal");
+  staticpro (&Qread_file_name_internal);
+
   Qminibuffer_completion_table = intern ("minibuffer-completion-table");
   staticpro (&Qminibuffer_completion_table);
 
@@ -1382,6 +1483,13 @@ syms_of_minibuf ()
   Qminibuffer_history = intern ("minibuffer-history");
   staticpro (&Qminibuffer_history);
 
+  Qminibuffer_setup_hook = intern ("minibuffer-setup-hook");
+  staticpro (&Qminibuffer_setup_hook);
+
+  DEFVAR_LISP ("minibuffer-setup-hook", &Vminibuffer_setup_hook, 
+    "Normal hook run just after entry to minibuffer.");
+  Vminibuffer_setup_hook = Qnil;
+
   DEFVAR_BOOL ("completion-auto-help", &auto_help,
     "*Non-nil means automatically provide help for invalid completion input.");
   auto_help = 1;
@@ -1434,6 +1542,10 @@ Each minibuffer output is added with\n\
     "Current position of redoing in the history list.");
   Vminibuffer_history_position = Qnil;
 
+  DEFVAR_BOOL ("minibuffer-auto-raise", &minibuffer_auto_raise,
+    "*Non-nil means entering the minibuffer raises the minibuffer's frame.");
+  minibuffer_auto_raise = 0;
+
   defsubr (&Sread_from_minibuffer);
   defsubr (&Seval_minibuffer);
   defsubr (&Sread_minibuffer);