Changes for automatic remapping of X colors on terminal frames:
[bpt/emacs.git] / src / minibuf.c
index e0bf54a..711dc2d 100644 (file)
@@ -1,5 +1,5 @@
 /* Minibuffer input and completion.
-   Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998
+   Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998, 1999
          Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA.  */
 
 
 #include <config.h>
+#include <stdio.h>
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
@@ -40,29 +41,37 @@ extern int quit_char;
    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;
 
 /* Data to remember during recursive minibuffer invocations  */
+
 Lisp_Object minibuf_save_list;
 
 /* Depth in minibuffer invocations.  */
+
 int minibuf_level;
 
 /* Nonzero means display completion help for invalid input.  */
+
 int auto_help;
 
 /* The maximum length of a minibuffer history.  */
+
 Lisp_Object Qhistory_length, Vhistory_length;
 
 /* Fread_minibuffer leaves the input here as a string. */
+
 Lisp_Object last_minibuf_string;
 
 /* Nonzero means let functions called when within a minibuffer 
    invoke recursive minibuffers (to read arguments, or whatever) */
+
 int enable_recursive_minibuffers;
 
 /* Nonzero means don't ignore text properties
    in Fread_from_minibuffer.  */
+
 int minibuffer_allow_text_properties;
 
 /* help-form is bound to this while in the minibuffer.  */
@@ -77,7 +86,7 @@ Lisp_Object Vminibuffer_history_variable;
 
 Lisp_Object Vminibuffer_history_position;
 
-Lisp_Object Qminibuffer_history;
+Lisp_Object Qminibuffer_history, Qbuffer_name_history;
 
 Lisp_Object Qread_file_name_internal;
 
@@ -107,18 +116,22 @@ int minibuffer_auto_raise;
 
 static Lisp_Object last_exact_completion;
 
-Lisp_Object Quser_variable_p;
-
-Lisp_Object Qminibuffer_default;
-
 /* Non-nil means it is the window for C-M-v to scroll
    when the minibuffer is selected.  */
+
 extern Lisp_Object Vminibuf_scroll_window;
 
 extern Lisp_Object Voverriding_local_map;
 
+Lisp_Object Quser_variable_p;
+
+Lisp_Object Qminibuffer_default;
+
 Lisp_Object Qcurrent_input_method, Qactivate_input_method;
 
+extern Lisp_Object Qmouse_face;
+
+extern Lisp_Object Qfield;
 \f
 /* Put minibuf on currently selected frame's minibuffer.
    We do this whenever the user starts a new minibuffer
@@ -127,17 +140,25 @@ Lisp_Object Qcurrent_input_method, Qactivate_input_method;
 void
 choose_minibuf_frame ()
 {
-  if (selected_frame != 0
-      && !EQ (minibuf_window, selected_frame->minibuffer_window))
+  if (FRAMEP (selected_frame)
+      && FRAME_LIVE_P (XFRAME (selected_frame))
+      && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
     {
+      struct frame *sf = XFRAME (selected_frame);
+      Lisp_Object buffer;
+      
       /* I don't think that any frames may validly have a null minibuffer
         window anymore.  */
-      if (NILP (selected_frame->minibuffer_window))
+      if (NILP (sf->minibuffer_window))
        abort ();
 
-      Fset_window_buffer (selected_frame->minibuffer_window,
-                         XWINDOW (minibuf_window)->buffer);
-      minibuf_window = selected_frame->minibuffer_window;
+      /* Under X, we come here with minibuf_window being the
+        minibuffer window of the unused termcap window created in
+        init_window_once.  That window doesn't have a buffer.  */
+      buffer = XWINDOW (minibuf_window)->buffer;
+      if (BUFFERP (buffer))
+       Fset_window_buffer (sf->minibuffer_window, buffer);
+      minibuf_window = sf->minibuffer_window;
     }
 
   /* Make sure no other frame has a minibuffer as its selected window,
@@ -149,7 +170,7 @@ choose_minibuf_frame ()
 
     FOR_EACH_FRAME (tail, frame)
       if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (XFRAME (frame))))
-         && !(XFRAME (frame) == selected_frame
+         && !(EQ (frame, selected_frame)
               && minibuf_level > 0))
        Fset_frame_selected_window (frame, Fframe_first_window (frame));
   }
@@ -189,6 +210,112 @@ static Lisp_Object read_minibuf P_ ((Lisp_Object, Lisp_Object,
                                     int, Lisp_Object,
                                     Lisp_Object, Lisp_Object,
                                     int, int));
+static Lisp_Object read_minibuf_noninteractive P_ ((Lisp_Object, Lisp_Object,
+                                                   Lisp_Object, Lisp_Object,
+                                                   int, Lisp_Object,
+                                                   Lisp_Object, Lisp_Object,
+                                                   int, int));
+static Lisp_Object string_to_object P_ ((Lisp_Object, Lisp_Object));
+
+
+/* Read a Lisp object from VAL and return it.  If VAL is an empty
+   string, and DEFALT is a string, read from DEFALT instead of VAL.  */
+
+static Lisp_Object
+string_to_object (val, defalt)
+     Lisp_Object val, defalt;
+{
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object expr_and_pos;
+  int pos;
+      
+  GCPRO2 (val, defalt);
+      
+  if (STRINGP (val) && XSTRING (val)->size == 0
+      && STRINGP (defalt))
+    val = defalt;
+      
+  expr_and_pos = Fread_from_string (val, Qnil, Qnil);
+  pos = XINT (Fcdr (expr_and_pos));
+  if (pos != XSTRING (val)->size)
+    {
+      /* Ignore trailing whitespace; any other trailing junk
+        is an error.  */
+      int i;
+      pos = string_char_to_byte (val, pos);
+      for (i = pos; i < STRING_BYTES (XSTRING (val)); i++)
+       {
+         int c = XSTRING (val)->data[i];
+         if (c != ' ' && c != '\t' && c != '\n')
+           error ("Trailing garbage following expression");
+       }
+    }
+      
+  val = Fcar (expr_and_pos);
+  RETURN_UNGCPRO (val);
+}
+
+
+/* Like read_minibuf but reading from stdin.  This function is called
+   from read_minibuf to do the job if noninteractive.  */
+
+static Lisp_Object
+read_minibuf_noninteractive (map, initial, prompt, backup_n, expflag,
+                            histvar, histpos, defalt, allow_props,
+                            inherit_input_method)
+     Lisp_Object map;
+     Lisp_Object initial;
+     Lisp_Object prompt;
+     Lisp_Object backup_n;
+     int expflag;
+     Lisp_Object histvar;
+     Lisp_Object histpos;
+     Lisp_Object defalt;
+     int allow_props;
+     int inherit_input_method;
+{
+  int size, len;
+  char *line, *s;
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object val;
+
+  fprintf (stdout, "%s", XSTRING (prompt)->data);
+  fflush (stdout);
+
+  size = 100;
+  len = 0;
+  line = (char *) xmalloc (size * sizeof *line);
+  while ((s = fgets (line + len, size - len, stdin)) != NULL
+        && (len = strlen (line),
+            len == size - 1 && line[len - 1] != '\n'))
+    {
+      size *= 2;
+      line = (char *) xrealloc (line, size);
+    }
+
+  if (s)
+    {
+      len = strlen (line);
+      
+      if (len > 0 && line[len - 1] == '\n')
+       line[--len] = '\0';
+      
+      val = build_string (line);
+      xfree (line);
+    }
+  else
+    {
+      xfree (line);
+      error ("Error reading from stdin");
+    }
+  
+  /* If Lisp form desired instead of string, parse it. */
+  if (expflag)
+    val = string_to_object (val, defalt);
+  
+  return val;
+}
+
 
 /* Read from the minibuffer using keymap MAP, initial contents INITIAL
    (a string), putting point minus BACKUP_N bytes from the end of INITIAL,
@@ -227,6 +354,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
   Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   Lisp_Object enable_multibyte;
+  extern Lisp_Object Qread_only, Qfront_sticky;
+  extern Lisp_Object Qrear_nonsticky;
 
   specbind (Qminibuffer_default, defalt);
 
@@ -256,6 +385,11 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
                build_string ("Command attempted to use minibuffer while in minibuffer"));
     }
 
+  if (noninteractive)
+    return read_minibuf_noninteractive (map, initial, prompt, backup_n,
+                                       expflag, histvar, histpos, defalt,
+                                       allow_props, inherit_input_method);
+
   /* Choose the minibuffer window and frame, and take action on them.  */
 
   choose_minibuf_frame ();
@@ -268,7 +402,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
   /* If the minibuffer window is on a different frame, save that
      frame's configuration too.  */
   mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
-  if (XFRAME (mini_frame) != selected_frame)
+  if (!EQ (mini_frame, selected_frame))
     record_unwind_protect (Fset_window_configuration,
                           Fcurrent_window_configuration (mini_frame));
 
@@ -302,7 +436,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
 
   /* Now that we can restore all those variables, start changing them.  */
 
-  minibuf_prompt_width = 0;    /* xdisp.c puts in the right value.  */
+  minibuf_prompt_width = 0;
   minibuf_prompt = Fcopy_sequence (prompt);
   Vminibuffer_history_position = histpos;
   Vminibuffer_history_variable = histvar;
@@ -337,11 +471,11 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
 
       for (buf_list = Vbuffer_alist;
           CONSP (buf_list);
-          buf_list = XCONS (buf_list)->cdr)
+          buf_list = XCDR (buf_list))
        {
          Lisp_Object other_buf;
 
-         other_buf = XCONS (XCONS (buf_list)->car)->cdr;
+         other_buf = XCDR (XCAR (buf_list));
          if (STRINGP (XBUFFER (other_buf)->directory))
            {
              current_buffer->directory = XBUFFER (other_buf)->directory;
@@ -350,8 +484,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
        }
     }
 
-  if (XFRAME (mini_frame) != selected_frame)
-    Fredirect_frame_focus (Fselected_frame (), mini_frame);
+  if (!EQ (mini_frame, selected_frame))
+    Fredirect_frame_focus (selected_frame, mini_frame);
 
   Vminibuf_scroll_window = selected_window;
   Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
@@ -369,6 +503,30 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
     unbind_to (count1, Qnil);
   }
 
+  if (!NILP (current_buffer->enable_multibyte_characters)
+      && ! STRING_MULTIBYTE (minibuf_prompt))
+    minibuf_prompt = Fstring_make_multibyte (minibuf_prompt);
+
+  /* Insert the prompt, record where it ends.  */
+  Finsert (1, &minibuf_prompt);
+  if (PT > BEG)
+    {
+      Fput_text_property (make_number (BEG), make_number (PT),
+                         Qfront_sticky, Qt, Qnil);
+      Fput_text_property (make_number (BEG), make_number (PT),
+                         Qrear_nonsticky, Qt, Qnil);
+      Fput_text_property (make_number (BEG), make_number (PT),
+                         Qfield, Qt, Qnil);
+      Fput_text_property (make_number (BEG), make_number (PT),
+                         Qread_only, Qt, Qnil);
+    }
+  
+  minibuf_prompt_width = current_column ();
+      
+  /* If appropriate, copy enable-multibyte-characters into the minibuffer.  */
+  if (inherit_input_method)
+    current_buffer->enable_multibyte_characters = enable_multibyte;
+
   /* Put in the initial input.  */
   if (!NILP (initial))
     {
@@ -377,20 +535,13 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
        Fforward_char (backup_n);
     }
 
-  echo_area_glyphs = 0;
-  /* This is in case the minibuffer-setup-hook calls Fsit_for.  */
-  previous_echo_glyphs = 0;
-
+  clear_message (1, 1);
   current_buffer->keymap = map;
 
   /* Turn on an input method stored in INPUT_METHOD if any.  */
   if (STRINGP (input_method) && !NILP (Ffboundp (Qactivate_input_method)))
     call1 (Qactivate_input_method, input_method);
 
-  /* If appropriate, copy enable-multibyte-characters into the minibuffer.  */
-  if (inherit_input_method)
-    current_buffer->enable_multibyte_characters = enable_multibyte;
-
   /* 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).  */
@@ -398,26 +549,24 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
       && !NILP (Vrun_hooks))
     call1 (Vrun_hooks, Qminibuffer_setup_hook);
 
-/* ??? 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 ((FRAME_CURSOR_Y (selected_frame)
-       >= XFASTINT (XWINDOW (minibuf_window)->top))
+  if (XWINDOW (minibuf_window)->cursor.vpos >= 0
       && !noninteractive)
     {
-      FRAME_CURSOR_X (selected_frame)
-       = FRAME_LEFT_SCROLL_BAR_WIDTH (selected_frame);
-      update_frame (selected_frame, 1, 1);
+      XWINDOW (minibuf_window)->cursor.hpos = 0;
+      XWINDOW (minibuf_window)->cursor.x = 0;
+      XWINDOW (minibuf_window)->must_be_updated_p = 1;
+      update_frame (XFRAME (selected_frame), 1, 1);
+      if (rif && rif->flush_display)
+       rif->flush_display (XFRAME (XWINDOW (minibuf_window)->frame));
     }
 
   /* Make minibuffer contents into a string.  */
   Fset_buffer (minibuffer);
-  val = make_buffer_string (1, Z, allow_props);
-#if 0  /* make_buffer_string should handle the gap.  */
-  bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
-#endif
+  val = Ffield_string (make_number (ZV), allow_props ? Qt : Qnil);
 
   /* VAL is the string of minibuffer text.  */
 
@@ -425,12 +574,16 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
 
   /* 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))
+      && SYMBOLP (Vminibuffer_history_variable))
     {
       /* 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;
+
+      /* If variable is unbound, make it nil.  */
+      if (EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
+       Fset (Vminibuffer_history_variable, Qnil);
+
       histval = Fsymbol_value (Vminibuffer_history_variable);
 
       /* The value of the history variable must be a cons or nil.  Other
@@ -464,31 +617,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag,
 
   /* If Lisp form desired instead of string, parse it. */
   if (expflag)
-    {
-      Lisp_Object expr_and_pos;
-      unsigned char *p;
-      int pos;
-
-      if (STRINGP (val) && XSTRING (val)->size == 0
-         && STRINGP (defalt))
-       val = defalt;
-
-      expr_and_pos = Fread_from_string (val, Qnil, Qnil);
-      pos = XINT (Fcdr (expr_and_pos));
-      if (pos != XSTRING (val)->size)
-       {
-         /* Ignore trailing whitespace; any other trailing junk is an error.  */
-         int i;
-         pos = string_char_to_byte (val, pos);
-         for (i = pos; i < XSTRING (val)->size_byte; i++)
-           {
-             int c = XSTRING (val)->data[i];
-             if (c != ' ' && c != '\t' && c != '\n')
-               error ("Trailing garbage following expression");
-           }
-       }
-      val = Fcar (expr_and_pos);
-    }
+    val = string_to_object (val, defalt);
 
   /* The appropriate frame will get selected
      in set-window-configuration.  */
@@ -524,7 +653,7 @@ get_minibuffer (depth)
         enabled in it.  */
       Fbuffer_enable_undo (buf);
 
-      XCONS (tail)->car = buf;
+      XCAR (tail) = buf;
     }
   else
     {
@@ -540,8 +669,8 @@ get_minibuffer (depth)
   return buf;
 }
 
-/* This function is called on exiting minibuffer, whether normally or not,
- and it restores the current window, buffer, etc. */
+/* This function is called on exiting minibuffer, whether normally or
  not, and it restores the current window, buffer, etc. */
 
 static Lisp_Object
 read_minibuf_unwind (data)
@@ -561,8 +690,8 @@ read_minibuf_unwind (data)
   minibuf_level--;
 
   window = minibuf_window;
-  /* To keep things predictable, in case it matters, let's be in the minibuffer
-     when we reset the relevant variables.  */
+  /* To keep things predictable, in case it matters, let's be in the
+     minibuffer when we reset the relevant variables.  */
   Fset_buffer (XWINDOW (window)->buffer);
 
   /* Restore prompt, etc, from outer minibuffer level.  */
@@ -598,11 +727,15 @@ read_minibuf_unwind (data)
     unbind_to (count, Qnil);
   }
 
+  /* When we get to the outmost level, make sure we resize the
+     mini-window back to its normal size.  */
+  if (minibuf_level == 0)
+    resize_mini_window (XWINDOW (window), 0);
+
   /* Make sure minibuffer window is erased, not ignored.  */
   windows_or_buffers_changed++;
   XSETFASTINT (XWINDOW (window)->last_modified, 0);
   XSETFASTINT (XWINDOW (window)->last_overlay_modified, 0);
-
   return Qnil;
 }
 \f
@@ -838,7 +971,6 @@ If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are a
   (prompt, def, require_match)
      Lisp_Object prompt, def, require_match;
 {
-  Lisp_Object tem;
   Lisp_Object args[4];
   
   if (BUFFERP (def))
@@ -855,7 +987,8 @@ If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are a
        }
 
       return Fcompleting_read (prompt, Vbuffer_alist, Qnil,
-                              require_match, Qnil, Qnil, def, Qnil);
+                              require_match, Qnil, Qbuffer_name_history,
+                              def, Qnil);
     }
   else
     {
@@ -867,6 +1000,19 @@ If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are a
     }
 }
 \f
+static Lisp_Object
+minibuf_conform_representation (string, basis)
+     Lisp_Object string, basis;
+{
+  if (STRING_MULTIBYTE (string) == STRING_MULTIBYTE (basis))
+    return string;
+
+  if (STRING_MULTIBYTE (string))
+    return Fstring_make_unibyte (string);
+  else
+    return Fstring_make_multibyte (string);
+}
+
 DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0,
   "Return common substring of all completions of STRING in ALIST.\n\
 Each car of each element of ALIST is tested to see if it begins with STRING.\n\
@@ -954,9 +1100,12 @@ or the symbol from the obarray.")
       /* Is this element a possible completion? */
 
       if (STRINGP (eltstring)
-         && XSTRING (string)->size_byte <= XSTRING (eltstring)->size_byte
-         && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
-                      XSTRING (string)->size_byte))
+         && XSTRING (string)->size <= XSTRING (eltstring)->size
+         && (tem = Fcompare_strings (eltstring, make_number (0),
+                                     make_number (XSTRING (string)->size),
+                                     string, make_number (0), Qnil,
+                                     completion_ignore_case ?Qt : Qnil),
+             EQ (Qt, tem)))
        {
          /* Yes. */
          Lisp_Object regexps;
@@ -965,9 +1114,9 @@ or the symbol from the obarray.")
 
          /* Ignore this element if it fails to match all the regexps.  */
          for (regexps = Vcompletion_regexp_list; CONSP (regexps);
-              regexps = XCONS (regexps)->cdr)
+              regexps = XCDR (regexps))
            {
-             tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
+             tem = Fstring_match (XCAR (regexps), eltstring, zero);
              if (NILP (tem))
                break;
            }
@@ -996,14 +1145,23 @@ or the symbol from the obarray.")
          if (NILP (bestmatch))
            {
              bestmatch = eltstring;
-             bestmatchsize = XSTRING (eltstring)->size_byte;
+             bestmatchsize = XSTRING (eltstring)->size;
            }
          else
            {
-             compare = min (bestmatchsize, XSTRING (eltstring)->size_byte);
-             matchsize = scmp (XSTRING (bestmatch)->data,
-                               XSTRING (eltstring)->data,
-                               compare);
+             compare = min (bestmatchsize, XSTRING (eltstring)->size);
+             tem = Fcompare_strings (bestmatch, make_number (0),
+                                     make_number (compare),
+                                     eltstring, make_number (0),
+                                     make_number (compare),
+                                     completion_ignore_case ? Qt : Qnil);
+             if (EQ (tem, Qt))
+               matchsize = compare;
+             else if (XINT (tem) < 0)
+               matchsize = - XINT (tem) - 1;
+             else
+               matchsize = XINT (tem) - 1;
+
              if (matchsize < 0)
                matchsize = compare;
              if (completion_ignore_case)
@@ -1012,8 +1170,8 @@ or the symbol from the obarray.")
                     use it as the best match rather than one that is not an
                     exact match.  This way, we get the case pattern
                     of the actual match.  */
-                 if ((matchsize == XSTRING (eltstring)->size_byte
-                      && matchsize < XSTRING (bestmatch)->size_byte)
+                 if ((matchsize == XSTRING (eltstring)->size
+                      && matchsize < XSTRING (bestmatch)->size)
                      ||
                      /* If there is more than one exact match ignoring case,
                         and one of them is exact including case,
@@ -1021,15 +1179,21 @@ or the symbol from the obarray.")
                      /* If there is no exact match ignoring case,
                         prefer a match that does not change the case
                         of the input.  */
-                     ((matchsize == XSTRING (eltstring)->size_byte)
+                     ((matchsize == XSTRING (eltstring)->size)
                       ==
-                      (matchsize == XSTRING (bestmatch)->size_byte)
-                      && !bcmp (XSTRING (eltstring)->data,
-                                XSTRING (string)->data,
-                                XSTRING (string)->size_byte)
-                      && bcmp (XSTRING (bestmatch)->data,
-                               XSTRING (string)->data,
-                               XSTRING (string)->size_byte)))
+                      (matchsize == XSTRING (bestmatch)->size)
+                      && (tem = Fcompare_strings (eltstring, make_number (0),
+                                                  make_number (XSTRING (string)->size),
+                                                  string, make_number (0),
+                                                  Qnil,
+                                                  Qnil),
+                          EQ (Qt, tem))
+                      && (tem = Fcompare_strings (bestmatch, make_number (0),
+                                                  make_number (XSTRING (string)->size),
+                                                  string, make_number (0),
+                                                  Qnil,
+                                                  Qnil),
+                          ! EQ (Qt, tem))))
                    bestmatch = eltstring;
                }
              bestmatchsize = matchsize;
@@ -1042,19 +1206,21 @@ or the symbol from the obarray.")
   /* If we are ignoring case, and there is no exact match,
      and no additional text was supplied,
      don't change the case of what the user typed.  */
-  if (completion_ignore_case && bestmatchsize == XSTRING (string)->size_byte
-      && XSTRING (bestmatch)->size_byte > bestmatchsize)
-    return string;
+  if (completion_ignore_case && bestmatchsize == XSTRING (string)->size
+      && XSTRING (bestmatch)->size > bestmatchsize)
+    return minibuf_conform_representation (string, bestmatch);
 
   /* Return t if the supplied string is an exact match (counting case);
      it does not require any change to be made.  */
-  if (matchcount == 1 && bestmatchsize == XSTRING (string)->size_byte
-      && !bcmp (XSTRING (bestmatch)->data, XSTRING (string)->data,
-               bestmatchsize))
+  if (matchcount == 1 && bestmatchsize == XSTRING (string)->size
+      && (tem = Fcompare_strings (bestmatch, make_number (0),
+                                 make_number (bestmatchsize),
+                                 string, make_number (0),
+                                 make_number (bestmatchsize),
+                                 Qnil),
+         EQ (Qt, tem)))
     return Qt;
 
-  bestmatchsize = string_byte_to_char (bestmatch, bestmatchsize);
-
   XSETFASTINT (zero, 0);               /* Else extract the part in which */
   XSETFASTINT (end, bestmatchsize);    /* all completions agree */
   return Fsubstring (bestmatch, zero, end);
@@ -1071,7 +1237,6 @@ scmp (s1, s2, len)
      int len;
 {
   register int l = len;
-  register unsigned char *start = s1;
 
   if (completion_ignore_case)
     {
@@ -1182,15 +1347,19 @@ are ignored unless STRING itself starts with a space.")
       /* Is this element a possible completion? */
 
       if (STRINGP (eltstring)
-         && XSTRING (string)->size_byte <= XSTRING (eltstring)->size_byte
+         && XSTRING (string)->size <= XSTRING (eltstring)->size
          /* If HIDE_SPACES, reject alternatives that start with space
             unless the input starts with space.  */
-         && ((XSTRING (string)->size_byte > 0
+         && ((STRING_BYTES (XSTRING (string)) > 0
               && XSTRING (string)->data[0] == ' ')
              || XSTRING (eltstring)->data[0] != ' '
              || NILP (hide_spaces))
-         && 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
-                      XSTRING (string)->size_byte))
+         && (tem = Fcompare_strings (eltstring, make_number (0),
+                                     make_number (XSTRING (string)->size),
+                                     string, make_number (0),
+                                     make_number (XSTRING (string)->size),
+                                     completion_ignore_case ? Qt : Qnil),
+             EQ (Qt, tem)))
        {
          /* Yes. */
          Lisp_Object regexps;
@@ -1199,9 +1368,9 @@ are ignored unless STRING itself starts with a space.")
 
          /* Ignore this element if it fails to match all the regexps.  */
          for (regexps = Vcompletion_regexp_list; CONSP (regexps);
-              regexps = XCONS (regexps)->cdr)
+              regexps = XCDR (regexps))
            {
-             tem = Fstring_match (XCONS (regexps)->car, eltstring, zero);
+             tem = Fstring_match (XCAR (regexps), eltstring, zero);
              if (NILP (tem))
                break;
            }
@@ -1234,6 +1403,7 @@ are ignored unless STRING itself starts with a space.")
 Lisp_Object Vminibuffer_completion_table, Qminibuffer_completion_table;
 Lisp_Object Vminibuffer_completion_predicate, Qminibuffer_completion_predicate;
 Lisp_Object Vminibuffer_completion_confirm, Qminibuffer_completion_confirm;
+Lisp_Object Vminibuffer_completing_file_name;
 
 /* This comment supplies the doc string for completing-read,
    for make-docfile to see.  We cannot put this in the real DEFUN
@@ -1244,7 +1414,7 @@ DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 8, 0,
 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' and `all-completions' for more details
+See `try-completion' and `all-completions' for more details\n\
  on completion, TABLE, and PREDICATE.\n\
 \n\
 If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless\n\
@@ -1282,7 +1452,6 @@ DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 8, 0,
   int pos = 0;
   int count = specpdl_ptr - specpdl;
   struct gcpro gcpro1;
-  int disable_multibyte = EQ (table, Qread_file_name_internal);
 
   GCPRO1 (def);
 
@@ -1356,10 +1525,22 @@ test_completion (txt)
       tem = oblookup (Vminibuffer_completion_table,
                      XSTRING (txt)->data,
                      XSTRING (txt)->size,
-                     XSTRING (txt)->size_byte);
+                     STRING_BYTES (XSTRING (txt)));
       if (!SYMBOLP (tem))
-       return Qnil;
-      else if (!NILP (Vminibuffer_completion_predicate))
+       {
+         if (STRING_MULTIBYTE (txt))
+           txt = Fstring_make_unibyte (txt);
+         else
+           txt = Fstring_make_multibyte (txt);
+
+         tem = oblookup (Vminibuffer_completion_table,
+                         XSTRING (txt)->data,
+                         XSTRING (txt)->size,
+                         STRING_BYTES (XSTRING (txt)));
+         if (!SYMBOLP (tem))
+           return Qnil;
+       }
+      if (!NILP (Vminibuffer_completion_predicate))
        return call1 (Vminibuffer_completion_predicate, tem);
       else
        return Qt;
@@ -1385,7 +1566,8 @@ do_completion ()
   Lisp_Object last;
   struct gcpro gcpro1, gcpro2;
 
-  completion = Ftry_completion (Fbuffer_string (), Vminibuffer_completion_table,
+  completion = Ftry_completion (Ffield_string (ZV),
+                               Vminibuffer_completion_table,
                                Vminibuffer_completion_predicate);
   last = last_exact_completion;
   last_exact_completion = Qnil;
@@ -1407,15 +1589,16 @@ do_completion ()
     }
 
   /* compiler bug */
-  tem = Fstring_equal (completion, Fbuffer_string());
-  if (completedp = NILP (tem))
+  tem = Fstring_equal (completion, Ffield_string(ZV));
+  completedp = NILP (tem);
+  if (completedp)
     {
-      Ferase_buffer ();                /* Some completion happened */
+      Fdelete_field (make_number (ZV)); /* Some completion happened */
       Finsert (1, &completion);
     }
 
   /* It did find a match.  Do we match some possibility exactly now? */
-  tem = test_completion (Fbuffer_string ());
+  tem = test_completion (Ffield_string(ZV));
   if (NILP (tem))
     {
       /* not an exact match */
@@ -1439,7 +1622,7 @@ do_completion ()
   last_exact_completion = completion;
   if (!NILP (last))
     {
-      tem = Fbuffer_string ();
+      tem = Ffield_string (ZV);
       if (!NILP (Fequal (tem, last)))
        Fminibuffer_completion_help ();
     }
@@ -1456,9 +1639,6 @@ assoc_for_completion (key, list)
 {
   register Lisp_Object tail;
 
-  if (completion_ignore_case)
-    key = Fupcase (key);
-
   for (tail = list; !NILP (tail); tail = Fcdr (tail))
     {
       register Lisp_Object elt, tem, thiscar;
@@ -1467,10 +1647,11 @@ assoc_for_completion (key, list)
       thiscar = Fcar (elt);
       if (!STRINGP (thiscar))
        continue;
-      if (completion_ignore_case)
-       thiscar = Fupcase (thiscar);
-      tem = Fequal (thiscar, key);
-      if (!NILP (tem)) return elt;
+      tem = Fcompare_strings (thiscar, make_number (0), Qnil,
+                             key, make_number (0), Qnil,
+                             completion_ignore_case ? Qt : Qnil);
+      if (EQ (tem, Qt))
+       return elt;
       QUIT;
     }
   return Qnil;
@@ -1487,9 +1668,9 @@ scroll the window of possible completions.")
   register int i;
   Lisp_Object window, tem;
 
-  /* If the previous command was not this, then mark the completion
-     buffer obsolete.  */
-  if (! EQ (current_kboard->Vlast_command, this_command))
+  /* If the previous command was not this,
+     mark the completion buffer obsolete.  */
+  if (! EQ (current_kboard->Vlast_command, Vthis_command))
     Vminibuf_scroll_window = Qnil;
 
   window = Vminibuf_scroll_window;
@@ -1562,10 +1743,10 @@ a repetition of this command will exit.")
   Lisp_Object val;
 
   /* Allow user to specify null string */
-  if (BEGV == ZV)
+  if (Ffield_beginning (ZV, Qnil) == ZV)
     goto exit;
 
-  if (!NILP (test_completion (Fbuffer_string ())))
+  if (!NILP (test_completion (Ffield_string (ZV))))
     goto exit;
 
   /* Call do_completion, but ignore errors.  */
@@ -1604,15 +1785,16 @@ is added, provided that matches some possible completion.\n\
 Return nil if there is no valid completion, else t.")
   ()
 {
-  Lisp_Object completion, tem;
+  Lisp_Object completion, tem, tem1;
   register int i, i_byte;
   register unsigned char *completion_string;
   struct gcpro gcpro1, gcpro2;
+  int prompt_end_charpos;
 
   /* 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 (),
+  completion = Ftry_completion (Ffield_string (ZV),
                                Vminibuffer_completion_table,
                                Vminibuffer_completion_predicate);
   if (NILP (completion))
@@ -1625,7 +1807,7 @@ Return nil if there is no valid completion, else t.")
     return Qnil;
 
 #if 0 /* How the below code used to look, for reference. */
-  tem = Fbuffer_string ();
+  tem = Ffield_string (ZV);
   b = XSTRING (tem)->data;
   i = ZV - 1 - XSTRING (completion)->size;
   p = XSTRING (completion)->data;
@@ -1641,55 +1823,77 @@ Return nil if there is no valid completion, else t.")
     }
 #else /* Rewritten code */
   {
-    register unsigned char *buffer_string;
-    int buffer_nbytes, completion_nbytes;
+    int buffer_nchars, completion_nchars;
 
     CHECK_STRING (completion, 0);
-    tem = Fbuffer_string ();
+    tem = Ffield_string (ZV);
     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))
+    if (! NILP (Vminibuffer_completing_file_name))
       {
        Lisp_Object substituted;
        substituted = Fsubstitute_in_file_name (tem);
        if (! EQ (substituted, tem))
          {
            tem = substituted;
-           Ferase_buffer ();
+           Fdelete_field (make_number (ZV));
            insert_from_string (tem, 0, 0, XSTRING (tem)->size,
-                               XSTRING (tem)->size_byte, 0);
+                               STRING_BYTES (XSTRING (tem)), 0);
          }
       }
-    buffer_string = XSTRING (tem)->data;
-    completion_string = XSTRING (completion)->data;
-    buffer_nbytes = XSTRING (tem)->size_byte; /* ie ZV_BYTE - BEGV_BYTE */
-    completion_nbytes = XSTRING (completion)->size_byte;
-    i_byte = buffer_nbytes - completion_nbytes;
-    if (i_byte > 0 ||
-       0 <= scmp (buffer_string, completion_string, buffer_nbytes))
+    buffer_nchars = XSTRING (tem)->size; /* ie ZV - BEGV */
+    completion_nchars = XSTRING (completion)->size;
+    i = buffer_nchars - completion_nchars;
+    if (i > 0
+       ||
+       (tem1 = Fcompare_strings (tem, make_number (0),
+                                 make_number (buffer_nchars),
+                                 completion, make_number (0),
+                                 make_number (buffer_nchars),
+                                 completion_ignore_case ? Qt : Qnil),
+        ! EQ (tem1, Qt)))
       {
-       /* Set buffer to longest match of buffer tail and completion head. */
-       if (i_byte <= 0) i_byte = 1;
-       buffer_string += i_byte;
-       buffer_nbytes -= i_byte;
-       while (0 <= scmp (buffer_string++, completion_string, buffer_nbytes--))
-         i_byte++;
-       del_range_byte (1, i_byte + 1, 1);
+       int start_pos;
+
+       /* Set buffer to longest match of buffer tail and completion head.  */
+       if (i <= 0) i = 1;
+       start_pos= i;
+       buffer_nchars -= i;
+       while (i > 0)
+         {
+           tem1 = Fcompare_strings (tem, make_number (start_pos), Qnil,
+                                    completion, make_number (0),
+                                    make_number (buffer_nchars),
+                                    completion_ignore_case ? Qt : Qnil);
+           start_pos++;
+           if (EQ (tem1, Qt))
+             break;
+           i++;
+           buffer_nchars--;
+         }
+       del_range (1, i + 1);
        SET_PT_BOTH (ZV, ZV_BYTE);
       }
     UNGCPRO;
   }
 #endif /* Rewritten code */
-  i_byte = ZV_BYTE - BEGV_BYTE;
-  i = ZV - BEGV;
+  
+  prompt_end_charpos = Ffield_beginning (make_number (ZV), Qnil);
+
+  {
+    int prompt_end_bytepos;
+    prompt_end_bytepos = CHAR_TO_BYTE (prompt_end_charpos);
+    i = ZV - prompt_end_charpos;
+    i_byte = ZV_BYTE - prompt_end_bytepos;
+  }
 
   /* If completion finds next char not unique,
      consider adding a space or a hyphen. */
   if (i == XSTRING (completion)->size)
     {
       GCPRO1 (completion);
-      tem = Ftry_completion (concat2 (Fbuffer_string (), build_string (" ")),
+      tem = Ftry_completion (concat2 (Ffield_string (ZV), build_string (" ")),
                             Vminibuffer_completion_table,
                             Vminibuffer_completion_predicate);
       UNGCPRO;
@@ -1700,7 +1904,7 @@ Return nil if there is no valid completion, else t.")
        {
          GCPRO1 (completion);
          tem =
-           Ftry_completion (concat2 (Fbuffer_string (), build_string ("-")),
+           Ftry_completion (concat2 (Ffield_string (ZV), build_string ("-")),
                             Vminibuffer_completion_table,
                             Vminibuffer_completion_predicate);
          UNGCPRO;
@@ -1714,12 +1918,12 @@ Return nil if there is no valid completion, else t.")
      i gets index in string of where to stop completing.  */
   {
     int len, c;
-
+    int bytes = STRING_BYTES (XSTRING (completion));
     completion_string = XSTRING (completion)->data;
-    for (; i_byte < XSTRING (completion)->size_byte; i_byte += len, i++)
+    for (; i_byte < STRING_BYTES (XSTRING (completion)); i_byte += len, i++)
       {
        c = STRING_CHAR_AND_LENGTH (completion_string + i_byte,
-                                   XSTRING (completion)->size - i_byte,
+                                   bytes - i_byte,
                                    len);
        if (SYNTAX (c) != Sword)
          {
@@ -1732,7 +1936,7 @@ Return nil if there is no valid completion, else t.")
 
   /* If got no characters, print help for user.  */
 
-  if (i_byte == ZV_BYTE - BEGV_BYTE)
+  if (i == ZV - prompt_end_charpos)
     {
       if (auto_help)
        Fminibuffer_completion_help ();
@@ -1741,7 +1945,7 @@ Return nil if there is no valid completion, else t.")
 
   /* Otherwise insert in minibuffer the chars we got */
 
-  Ferase_buffer ();
+  Fdelete_field (make_number (ZV));
   insert_from_string (completion, 0, 0, i, i_byte, 1);
   return Qt;
 }
@@ -1752,7 +1956,9 @@ DEFUN ("display-completion-list", Fdisplay_completion_list, Sdisplay_completion_
 Each element may be just a symbol or string\n\
 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\
+The actual completion alternatives, as inserted, are given `mouse-face'\n\
+properties of `highlight'.\n\
+At the end, this runs the normal hook `completion-setup-hook'.\n\
 It can find the completion buffer in `standard-output'.")
   (completions)
      Lisp_Object completions;
@@ -1782,7 +1988,7 @@ It can find the completion buffer in `standard-output'.")
       write_string ("Possible completions are:", -1);
       for (tail = completions, i = 0; !NILP (tail); tail = Fcdr (tail), i++)
        {
-         Lisp_Object tem;
+         Lisp_Object tem, string;
          int length;
          Lisp_Object startpos, endpos;
 
@@ -1816,7 +2022,7 @@ It can find the completion buffer in `standard-output'.")
             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)
+             || (column > 0 && length > 45))
            {
              Fterpri (Qnil);
              column = 0;
@@ -1848,15 +2054,58 @@ It can find the completion buffer in `standard-output'.")
                                    Qnil, Vstandard_output);
            }
 
-         /* Output this element and update COLUMN.  */
+         /* Output this element.
+            If necessary, convert it to unibyte or to multibyte first.  */
          if (CONSP (elt))
+           string = Fcar (elt);
+         else
+           string = elt;
+         if (NILP (current_buffer->enable_multibyte_characters)
+             && STRING_MULTIBYTE (string))
+           string = Fstring_make_unibyte (string);
+         else if (!NILP (current_buffer->enable_multibyte_characters)
+                  && !STRING_MULTIBYTE (string))
+           string = Fstring_make_multibyte (string);
+
+         if (BUFFERP (Vstandard_output))
            {
-             Fprinc (Fcar (elt), Qnil);
-             Fprinc (Fcar (Fcdr (elt)), Qnil);
+             XSETINT (startpos, BUF_PT (XBUFFER (Vstandard_output)));
+
+             Fprinc (string, Qnil);
+
+             XSETINT (endpos, BUF_PT (XBUFFER (Vstandard_output)));
+
+             Fput_text_property (startpos, endpos,
+                                 Qmouse_face, intern ("highlight"),
+                                 Vstandard_output);
            }
          else
-           Fprinc (elt, Qnil);
+           {
+             Fprinc (string, Qnil);
+           }
 
+         /* Output the annotation for this element.  */
+         if (CONSP (elt))
+           {
+             if (BUFFERP (Vstandard_output))
+               {
+                 XSETINT (startpos, BUF_PT (XBUFFER (Vstandard_output)));
+
+                 Fprinc (Fcar (Fcdr (elt)), Qnil);
+
+                 XSETINT (endpos, BUF_PT (XBUFFER (Vstandard_output)));
+
+                 Fset_text_properties (startpos, endpos, Qnil,
+                                       Vstandard_output);
+               }
+             else
+               {
+                 Fprinc (Fcar (Fcdr (elt)), Qnil);
+               }
+           }
+
+
+         /* Update COLUMN for what we have output.  */
          column += length;
 
          /* If output is to a buffer, recompute COLUMN in a way
@@ -1890,11 +2139,11 @@ DEFUN ("minibuffer-completion-help", Fminibuffer_completion_help, Sminibuffer_co
   Lisp_Object completions;
 
   message ("Making completion list...");
-  completions = Fall_completions (Fbuffer_string (),
+  completions = Fall_completions (Ffield_string (ZV),
                                  Vminibuffer_completion_table,
                                  Vminibuffer_completion_predicate,
                                  Qt);
-  echo_area_glyphs = 0;
+  clear_message (1, 0);
 
   if (NILP (completions))
     {
@@ -1913,7 +2162,7 @@ DEFUN ("self-insert-and-exit", Fself_insert_and_exit, Sself_insert_and_exit, 0,
   ()
 {
   if (INTEGERP (last_command_char))
-    internal_self_insert (last_command_char, 0);
+    internal_self_insert (XINT (last_command_char), 0);
   else
     bitch_at_user ();
 
@@ -1942,15 +2191,6 @@ 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
 /* Temporarily display the string M at the end of the current
    minibuffer contents.  This is used to display things like
@@ -1977,7 +2217,7 @@ temp_echo_area_glyphs (m)
   SET_PT_BOTH (opoint, opoint_byte);
   Vinhibit_quit = Qt;
   Fsit_for (make_number (2), Qnil, Qnil);
-  del_range_both (osize, ZV, osize_byte, ZV_BYTE, 1);
+  del_range_both (osize, osize_byte, ZV, ZV_BYTE, 1);
   SET_PT_BOTH (opoint, opoint_byte);
   if (!NILP (Vquit_flag))
     {
@@ -2044,6 +2284,10 @@ syms_of_minibuf ()
   Qminibuffer_history = intern ("minibuffer-history");
   staticpro (&Qminibuffer_history);
 
+  Qbuffer_name_history = intern ("buffer-name-history");
+  staticpro (&Qbuffer_name_history);
+  Fset (Qbuffer_name_history, Qnil);
+
   Qminibuffer_setup_hook = intern ("minibuffer-setup-hook");
   staticpro (&Qminibuffer_setup_hook);
 
@@ -2113,6 +2357,11 @@ t means to return a list of all possible completions of STRING.\n\
     "Non-nil => demand confirmation of completion before exiting minibuffer.");
   Vminibuffer_completion_confirm = Qnil;
 
+  DEFVAR_LISP ("minibuffer-completing-file-name",
+              &Vminibuffer_completing_file_name,
+    "Non-nil means completing file names.");
+  Vminibuffer_completing_file_name = Qnil;
+
   DEFVAR_LISP ("minibuffer-help-form", &Vminibuffer_help_form,
     "Value that `help-form' takes on inside the minibuffer.");
   Vminibuffer_help_form = Qnil;
@@ -2140,7 +2389,7 @@ Some uses of the echo area also raise that frame (since they use it too).");
 
   DEFVAR_BOOL ("minibuffer-allow-text-properties",
               &minibuffer_allow_text_properties,
-    "Non-nil means `read-from-miniffer' should not discard text properties.\n\
+    "Non-nil means `read-from-minibuffer' should not discard text properties.\n\
 This also affects `read-string', but it does not affect `read-minibuffer',\n\
 `read-no-blanks-input', or any of the functions that do minibuffer input\n\
 with completion; they always discard text properties.");
@@ -2157,7 +2406,6 @@ with completion; they always discard text properties.");
   defsubr (&Sread_no_blanks_input);
   defsubr (&Sminibuffer_depth);
   defsubr (&Sminibuffer_prompt);
-  defsubr (&Sminibuffer_prompt_width);
 
   defsubr (&Stry_completion);
   defsubr (&Sall_completions);