* etags.c (outf, outfiledir): renamed to tagf, tagfiledir.
[bpt/emacs.git] / src / minibuf.c
index 49b3c4d..ddb8ae7 100644 (file)
@@ -79,14 +79,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.  */
 
@@ -98,6 +103,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. */
 
@@ -174,6 +183,11 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
   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
@@ -199,8 +213,9 @@ 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;
 
+         other_buf = XCONS (XCONS (buf_list)->car)->cdr;
          if (XTYPE (XBUFFER (other_buf)->directory) == Lisp_String)
            {
              current_buffer->directory = XBUFFER (other_buf)->directory;
@@ -210,7 +225,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;
@@ -251,6 +267,10 @@ read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
 /* ??? MCC did redraw_screen here if switching screens.  */
   recursive_edit_1 ();
 
+  if (!NILP (Vminibuffer_exit_hook) && !EQ (Vminibuffer_exit_hook, Qunbound)
+      && !NILP (Vrun_hooks))
+    call1 (Vrun_hooks, Qminibuffer_exit_hook);
+
   /* If cursor is on the minibuffer line,
      show the user we have exited by putting it in column 0.  */
   if ((FRAME_CURSOR_Y (selected_frame)
@@ -288,14 +308,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.  */
+    {
+      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);
+    }
 
   UNGCPRO;
-
-  return val;
+  return unbind_to (count, val); /* The appropriate frame will get selected
+                                   in set-window-configuration.  */
 }
 
 /* Return a buffer to be used as the minibuffer at depth `depth'.
@@ -307,7 +334,7 @@ get_minibuffer (depth)
      int depth;
 {
   Lisp_Object tail, num, buf;
-  char name[14];
+  char name[24];
   extern Lisp_Object nconc2 ();
 
   XFASTINT (num) = depth;
@@ -638,12 +665,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 (XTYPE (eltstring) == Lisp_String
+         && XSTRING (string)->size <= XSTRING (eltstring)->size
+         && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
+                      XSTRING (string)->size))
        {
          /* Yes. */
+         Lisp_Object regexps;
+         Lisp_Object zero;
+         XFASTINT (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. */
 
@@ -837,6 +879,21 @@ The argument given to PREDICATE is the alist element or the symbol from the obar
                       XSTRING (string)->size))
        {
          /* Yes. */
+         Lisp_Object regexps;
+         Lisp_Object zero;
+         XFASTINT (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. */
 
@@ -967,7 +1024,7 @@ 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;
@@ -993,7 +1050,9 @@ do_completion ()
   Lisp_Object completion, tem;
   int completedp;
   Lisp_Object last;
+  struct gcpro gcpro1, gcpro2;
 
+  GCPRO2 (completion, last);
   completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
                                Vminibuffer_completion_predicate);
   last = last_exact_completion;
@@ -1003,11 +1062,15 @@ do_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());
@@ -1045,7 +1108,9 @@ do_completion ()
                 Qlambda);
 
   if (NILP (tem))
-    { /* not an exact match */
+    {
+      /* not an exact match */
+      UNGCPRO;
       if (completedp)
        return 5;
       else if (auto_help)
@@ -1055,7 +1120,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.  */
@@ -1066,9 +1134,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
@@ -1100,10 +1169,42 @@ assoc_for_completion (key, list)
 
 DEFUN ("minibuffer-complete", Fminibuffer_complete, Sminibuffer_complete, 0, 0, "",
   "Complete the minibuffer contents as far as possible.\n\
-Return nil if there is no valid completion, else t.")
+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);
+      else
+       /* Else scroll down one screen.  */
+       Fscroll_other_window (Qnil);
+
+      set_buffer_internal (obuf);
+      return Qnil;
+    }
+
+  i = do_completion ();
   switch (i)
     {
     case 0:
@@ -1433,6 +1534,25 @@ 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.")
+  ()
+{
+  if (!minibuf_prompt)
+    return Qnil;
+  return build_string (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;
+  XFASTINT (width) = minibuf_prompt_width;
+  return width;
+}
 \f
 init_minibuf_once ()
 {
@@ -1459,6 +1579,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;
 
@@ -1471,10 +1594,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;
@@ -1531,6 +1661,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);
@@ -1540,6 +1674,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);