]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(Fsignal): Handle case that backtrace_list is null.
[gnu-emacs] / src / xdisp.c
index e0206ca7ad392493c29e71f6fed94297d34226b4..b9941f956ffa7ad590047d18799f097631d690e2 100644 (file)
@@ -186,6 +186,7 @@ Boston, MA 02111-1307, USA.  */
 #include "coding.h"
 #include "process.h"
 #include "region-cache.h"
+#include "fontset.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -219,7 +220,7 @@ Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
 Lisp_Object Qredisplay_end_trigger_functions;
 Lisp_Object Qinhibit_point_motion_hooks;
-Lisp_Object QCeval, Qwhen, QCfile;
+Lisp_Object QCeval, Qwhen, QCfile, QCdata;
 Lisp_Object Qfontified;
 
 /* Functions called to fontify regions of text.  */
@@ -441,7 +442,7 @@ int line_number_displayed;
 
 /* Maximum buffer size for which to display line numbers.  */
 
-static int line_number_display_limit;
+Lisp_Object Vline_number_display_limit;
 
 /* line width to consider when repostioning for line number display */
 
@@ -479,7 +480,18 @@ int message_buf_print;
    specifying a fraction of the available height, or an integer
    specifying a number of lines.  */
 
-static Lisp_Object Vmax_mini_window_height;
+Lisp_Object Vmax_mini_window_height;
+
+/* Non-zero means messages should be displayed with truncated
+   lines instead of being continued.  */
+
+int message_truncate_lines;
+Lisp_Object Qmessage_truncate_lines;
+
+/* Non-zero means we want a hollow cursor in windows that are not
+   selected.  Zero means there's no cursor in such windows.  */
+
+int cursor_in_non_selected_windows;
 
 /* A scratch glyph row with contents used for generating truncation
    glyphs.  Also used in direct_output_for_insert.  */
@@ -507,6 +519,15 @@ static int last_max_ascent, last_height;
 int trace_redisplay_p;
 #endif
 
+/* Non-zero means automatically scroll windows horizontally to make
+   point visible.  */
+
+int automatic_hscrolling_p;
+
+/* A list of symbols, one for each supported image type.  */
+
+Lisp_Object Vimage_types;
+
 /* Value returned from text property handlers (see below).  */
 
 enum prop_handled
@@ -588,6 +609,7 @@ enum move_it_result
 \f
 /* Function prototypes.  */
 
+static int single_display_prop_intangible_p P_ ((Lisp_Object));
 static void ensure_echo_area_buffers P_ ((void));
 static struct glyph_row *row_containing_pos P_ ((struct window *, int,
                                                 struct glyph_row *,
@@ -659,7 +681,6 @@ static void init_from_display_pos P_ ((struct it *, struct window *,
                                       struct display_pos *));
 static void reseat_to_string P_ ((struct it *, unsigned char *,
                                  Lisp_Object, int, int, int, int));
-static int charset_at_position P_ ((struct text_pos));
 static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
                                                           int, int, int));
 void move_it_vertically_backward P_ ((struct it *, int));
@@ -869,7 +890,7 @@ window_box_edges (w, area, top_left_x, top_left_y,
 /* Return the next character from STR which is MAXLEN bytes long.
    Return in *LEN the length of the character.  This is like
    STRING_CHAR_AND_LENGTH but never returns an invalid character.  If
-   we find one, we return a `?', but with the length of the illegal
+   we find one, we return a `?', but with the length of the invalid
    character.  */
 
 static INLINE int
@@ -882,7 +903,7 @@ string_char_and_length (str, maxlen, len)
   c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
   if (!CHAR_VALID_P (c, 1))
     /* We may not change the length here because other places in Emacs
-       don't use this function, i.e. they silently accept illegal
+       don't use this function, i.e. they silently accept invalid
        characters.  */
     c = '?';
 
@@ -1017,38 +1038,13 @@ compute_string_pos (newpos, pos, string)
   xassert (CHARPOS (*newpos) >= CHARPOS (pos));
   
   if (STRING_MULTIBYTE (string))
-    *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos),
-                                      string);
+    *newpos = string_pos_nchars_ahead (pos, string,
+                                      CHARPOS (*newpos) - CHARPOS (pos));
   else
     BYTEPOS (*newpos) = CHARPOS (*newpos);
 }
 
 
-/* Return the charset of the character at position POS in
-   current_buffer.  */
-
-static int
-charset_at_position (pos)
-     struct text_pos pos;
-{
-  int c, multibyte_p;
-  unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos));
-
-  multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
-  if (multibyte_p)
-    {
-      int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
-                   - BYTEPOS (pos));
-      int len;
-      c = string_char_and_length (p, maxlen, &len);
-    }
-  else
-    c = *p;
-
-  return CHAR_CHARSET (c);
-}
-
-
 \f
 /***********************************************************************
                        Lisp form evaluation
@@ -1209,7 +1205,6 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   bzero (it, sizeof *it);
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
-  it->charset = CHARSET_ASCII;
   it->base_face_id = base_face_id;
 
   /* The window in which we iterate over current_buffer:  */
@@ -1217,6 +1212,16 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   it->w = w;
   it->f = XFRAME (w->frame);
 
+  /* Extra space between lines (on window systems only).  */
+  if (base_face_id == DEFAULT_FACE_ID
+      && FRAME_WINDOW_P (it->f))
+    {
+      if (NATNUMP (current_buffer->extra_line_spacing))
+       it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
+      else if (it->f->extra_line_spacing > 0)
+       it->extra_line_spacing = it->f->extra_line_spacing;
+    }
+
   /* If realized faces have been removed, e.g. because of face
      attribute changes of named faces, recompute them.  */
   if (FRAME_FACE_CACHE (it->f)->used == 0)
@@ -1592,6 +1597,7 @@ handle_stop (it)
 
   it->dpvec = NULL;
   it->current.dpvec_index = -1;
+  it->add_overlay_start = 0;
 
   do
     {
@@ -1601,7 +1607,7 @@ handle_stop (it)
       for (p = it_props; p->handler; ++p)
        {
          handled = p->handler (it);
-         
+
          if (handled == HANDLED_RECOMPUTE_PROPS)
            break;
          else if (handled == HANDLED_RETURN)
@@ -1789,7 +1795,6 @@ handle_fontified_prop (it)
 {
   Lisp_Object prop, pos;
   enum prop_handled handled = HANDLED_NORMALLY;
-  struct gcpro gcpro1;
 
   /* Get the value of the `fontified' property at IT's current buffer
      position.  (The `fontified' property doesn't have a special
@@ -1804,18 +1809,16 @@ handle_fontified_prop (it)
     {
       Lisp_Object args[2];
 
-      GCPRO1 (pos);
       /* Run the hook functions.  */
       args[0] = Qfontification_functions;
       args[1] = pos;
-      Frun_hook_with_args (make_number (2), args);
+      Frun_hook_with_args (2, args);
 
       /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
         something.  This avoids an endless loop if they failed to
         fontify the text for which reason ever.  */
       if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
        handled = HANDLED_RECOMPUTE_PROPS;
-      UNGCPRO;
     }
 
   return handled;
@@ -1916,7 +1919,6 @@ handle_face_prop (it)
     }
   
   it->face_id = new_face_id;
-  it->charset = CHARSET_ASCII;
   return HANDLED_NORMALLY;
 }
 
@@ -1975,12 +1977,11 @@ face_before_or_after_it_pos (it, before_p)
        {
          unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
          int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
-         int c, len, charset;
+         int c, len;
+         struct face *face = FACE_FROM_ID (it->f, face_id);
       
          c = string_char_and_length (p, rest, &len);
-         charset = CHAR_CHARSET (c);
-         if (charset != CHARSET_ASCII)
-           face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
+         face_id = FACE_FOR_CHAR (it->f, face, c);
        }
     }
   else
@@ -1993,7 +1994,7 @@ face_before_or_after_it_pos (it, before_p)
       pos = it->current.pos;
       
       if (before_p)
-       DEC_TEXT_POS (pos);
+       DEC_TEXT_POS (pos, it->multibyte_p);
       else
        {
          if (it->what == IT_COMPOSITION)
@@ -2001,7 +2002,7 @@ face_before_or_after_it_pos (it, before_p)
               composition.  */
            pos.charpos += it->cmp_len, pos.bytepos += it->len;
          else
-           INC_TEXT_POS (pos);
+           INC_TEXT_POS (pos, it->multibyte_p);
        }
       /* Determine face for CHARSET_ASCII, or unibyte.  */
       face_id = face_at_buffer_position (it->w,
@@ -2016,9 +2017,9 @@ face_before_or_after_it_pos (it, before_p)
         suitable for unibyte text if current_buffer is unibyte.  */
       if (it->multibyte_p)
        {
-         int charset = charset_at_position (pos);
-         if (charset != CHARSET_ASCII)
-           face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
+         int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos));
+         struct face *face = FACE_FROM_ID (it->f, face_id);
+         face_id = FACE_FOR_CHAR (it->f, face, c);
        }
     }
   
@@ -2051,7 +2052,8 @@ handle_invisible_prop (it)
       XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
       prop = Fget_text_property (charpos, Qinvisible, it->string);
 
-      if (!NILP (prop))
+      if (!NILP (prop)
+         && IT_STRING_CHARPOS (*it) < it->end_charpos)
        {
          handled = HANDLED_RECOMPUTE_PROPS;
          
@@ -2105,7 +2107,8 @@ handle_invisible_prop (it)
       prop = Fget_char_property (pos, Qinvisible, it->window);
       
       /* If we are on invisible text, skip over it.  */
-      if (TEXT_PROP_MEANS_INVISIBLE (prop))
+      if (TEXT_PROP_MEANS_INVISIBLE (prop)
+         && IT_CHARPOS (*it) < it->end_charpos)
        {
          /* Record whether we have to display an ellipsis for the
             invisible text.  */
@@ -2113,6 +2116,7 @@ handle_invisible_prop (it)
            = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
 
          handled = HANDLED_RECOMPUTE_PROPS;
+         it->add_overlay_start = IT_CHARPOS (*it);
          
          /* Loop skipping over invisible text.  The loop is left at
             ZV or with IT on the first char being visible again.  */
@@ -2303,7 +2307,6 @@ handle_single_display_prop (it, prop, object, position)
 {
   Lisp_Object value;
   int space_or_image_found_p = 0;
-
   Lisp_Object form;
 
   /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
@@ -2323,16 +2326,22 @@ handle_single_display_prop (it, prop, object, position)
       struct gcpro gcpro1;
       struct text_pos end_pos, pt;
       
-      end_pos = display_prop_end (it, object, *position);
       GCPRO1 (form);
+      end_pos = display_prop_end (it, object, *position);
 
       /* Temporarily set point to the end position, and then evaluate
         the form.  This makes `(eolp)' work as FORM.  */
-      CHARPOS (pt) = PT;
-      BYTEPOS (pt) = PT_BYTE;
-      TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
+      if (BUFFERP (object))
+       {
+         CHARPOS (pt) = PT;
+         BYTEPOS (pt) = PT_BYTE;
+         TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
+       }
+      
       form = eval_form (form);
-      TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
+      
+      if (BUFFERP (object))
+       TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
       UNGCPRO;  
     }
   
@@ -2434,7 +2443,7 @@ handle_single_display_prop (it, prop, object, position)
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
          it->voffset = - (XFLOATINT (value)
-                          * (face->font->ascent + face->font->descent));
+                          * (FONT_HEIGHT (face->font)));
        }
 #endif /* HAVE_WINDOW_SYSTEM */
     }
@@ -2448,9 +2457,9 @@ handle_single_display_prop (it, prop, object, position)
 
       /* Characters having this form of property are not displayed, so
          we have to find the end of the property.  */
-      space_or_image_found_p = 1;
       start_pos = *position;
       *position = display_prop_end (it, object, start_pos);
+      value = Qnil;
 
       /* Let's stop at the new position and assume that all
         text properties change there.  */
@@ -2497,6 +2506,8 @@ handle_single_display_prop (it, prop, object, position)
           || NILP (location))
          && valid_p)
        {
+         space_or_image_found_p = 1;
+         
          /* Save current settings of IT so that we can restore them
             when we are finished with the glyph property value.  */
          push_it (it);
@@ -2535,19 +2546,94 @@ handle_single_display_prop (it, prop, object, position)
              it->object = NILP (object) ? it->w->buffer : object;
              it->method = next_element_from_image;
              
-             /* Say that we don't have consumed the characters with
+             /* Say that we haven't consumed the characters with
                 `display' property yet.  The call to pop_it in
                 set_iterator_to_next will clean this up.  */
              *position = start_pos;
            }
 #endif /* HAVE_WINDOW_SYSTEM */
        }
+      else
+       /* Invalid property or property not supported.  Restore
+          the position to what it was before.  */
+       *position = start_pos;
     }
 
   return space_or_image_found_p;
 }
 
 
+/* Check if PROP is a display sub-property value whose text should be
+   treated as intangible.  */
+
+static int
+single_display_prop_intangible_p (prop)
+     Lisp_Object prop;
+{
+  /* Skip over `when FORM'.  */
+  if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
+    {
+      prop = XCDR (prop);
+      if (!CONSP (prop))
+       return 0;
+      prop = XCDR (prop);
+    }
+
+  if (!CONSP (prop))
+    return 0;
+
+  /* Skip over `margin LOCATION'.  If LOCATION is in the margins,
+     we don't need to treat text as intangible.  */
+  if (EQ (XCAR (prop), Qmargin))
+    {
+      prop = XCDR (prop);
+      if (!CONSP (prop))
+       return 0;
+
+      prop = XCDR (prop);
+      if (!CONSP (prop)
+         || EQ (XCAR (prop), Qleft_margin)
+         || EQ (XCAR (prop), Qright_margin))
+       return 0;
+    }
+  
+  return CONSP (prop) && EQ (XCAR (prop), Qimage);
+}
+
+
+/* Check if PROP is a display property value whose text should be
+   treated as intangible.  */
+
+int
+display_prop_intangible_p (prop)
+     Lisp_Object prop;
+{
+  if (CONSP (prop)
+      && CONSP (XCAR (prop))
+      && !EQ (Qmargin, XCAR (XCAR (prop))))
+    {
+      /* A list of sub-properties.  */
+      while (CONSP (prop))
+       {
+         if (single_display_prop_intangible_p (XCAR (prop)))
+           return 1;
+         prop = XCDR (prop);
+       }
+    }
+  else if (VECTORP (prop))
+    {
+      /* A vector of sub-properties.  */
+      int i;
+      for (i = 0; i < XVECTOR (prop)->size; ++i)
+       if (single_display_prop_intangible_p (XVECTOR (prop)->contents[i]))
+         return 1;
+    }
+  else
+    return single_display_prop_intangible_p (prop);
+
+  return 0;
+}
+
 \f
 /***********************************************************************
                        `composition' property
@@ -2616,6 +2702,7 @@ handle_composition_prop (it)
 
 struct overlay_entry
 {
+  Lisp_Object overlay;
   Lisp_Object string;
   int priority;
   int after_string_p;
@@ -2629,13 +2716,10 @@ static enum prop_handled
 handle_overlay_change (it)
      struct it *it;
 {
-  /* Overlays are handled in current_buffer only.  */
-  if (STRINGP (it->string))
-    return HANDLED_NORMALLY;
+  if (!STRINGP (it->string) && get_overlay_strings (it))
+    return HANDLED_RECOMPUTE_PROPS;
   else
-    return (get_overlay_strings (it)
-           ? HANDLED_RECOMPUTE_PROPS
-           : HANDLED_NORMALLY);
+    return HANDLED_NORMALLY;
 }
 
 
@@ -2664,6 +2748,12 @@ next_overlay_string (it)
       SET_TEXT_POS (it->current.string_pos, -1, -1);
       it->n_overlay_strings = 0;
       it->method = next_element_from_buffer;
+
+      /* If we're at the end of the buffer, record that we have
+        processed the overlay strings there already, so that
+        next_element_from_buffer doesn't try it again.  */
+      if (IT_CHARPOS (*it) >= it->end_charpos)
+       it->overlay_strings_at_end_processed_p = 1;
     }
   else
     {
@@ -2693,7 +2783,8 @@ next_overlay_string (it)
    comparison function for qsort in load_overlay_strings.  Overlay
    strings for the same position are sorted so that
 
-   1. All after-strings come in front of before-strings.
+   1. All after-strings come in front of before-strings, except
+   when they come from the same overlay.
    
    2. Within after-strings, strings are sorted so that overlay strings
    from overlays with higher priorities come first.
@@ -2713,8 +2804,14 @@ compare_overlay_entries (e1, e2)
   int result;
 
   if (entry1->after_string_p != entry2->after_string_p)
-    /* Let after-strings appear in front of before-strings.  */
-    result = entry1->after_string_p ? -1 : 1;
+    {
+      /* Let after-strings appear in front of before-strings if
+        they come from different overlays.  */
+      if (EQ (entry1->overlay, entry2->overlay))
+       result = entry1->after_string_p ? 1 : -1;
+      else
+       result = entry1->after_string_p ? -1 : 1;
+    }
   else if (entry1->after_string_p)
     /* After-strings sorted in order of decreasing priority.  */
     result = entry2->priority - entry1->priority;
@@ -2736,6 +2833,15 @@ compare_overlay_entries (e1, e2)
    strings that have already been loaded by previous calls to this
    function.
 
+   IT->add_overlay_start contains an additional overlay start
+   position to consider for taking overlay strings from, if non-zero.
+   This position comes into play when the overlay has an `invisible'
+   property, and both before and after-strings.  When we've skipped to
+   the end of the overlay, because of its `invisible' property, we
+   nevertheless want its before-string to appear.
+   IT->add_overlay_start will contain the overlay start position
+   in this case.
+
    Overlay strings are sorted so that after-string strings come in
    front of before-string strings.  Within before and after-strings,
    strings are sorted by overlay priority.  See also function
@@ -2774,18 +2880,16 @@ load_overlay_strings (it)
        }                                                               \
                                                                        \
       entries[n].string = (STRING);                                    \
+      entries[n].overlay = (OVERLAY);                                  \
       priority = Foverlay_get ((OVERLAY), Qpriority);                  \
-      entries[n].priority                                              \
-       = INTEGERP (priority) ? XFASTINT (priority) : 0;                \
+      entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0;  \
       entries[n].after_string_p = (AFTER_P);                           \
       ++n;                                                             \
     }                                                                  \
   while (0)
 
   /* Process overlay before the overlay center.  */
-  for (ov = current_buffer->overlays_before;
-       CONSP (ov);
-       ov = XCDR (ov))
+  for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
     {
       overlay = XCAR (ov);
       xassert (OVERLAYP (overlay));
@@ -2797,7 +2901,9 @@ load_overlay_strings (it)
 
       /* Skip this overlay if it doesn't start or end at IT's current
         position.  */
-      if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+      if (end != IT_CHARPOS (*it)
+         && start != IT_CHARPOS (*it)
+         && it->add_overlay_start != IT_CHARPOS (*it))
        continue;
       
       /* Skip this overlay if it doesn't apply to IT->w.  */
@@ -2806,7 +2912,8 @@ load_overlay_strings (it)
        continue;
 
       /* If overlay has a non-empty before-string, record it.  */
-      if (start == IT_CHARPOS (*it)
+      if ((start == IT_CHARPOS (*it)
+          || start == it->add_overlay_start)
          && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
          && XSTRING (str)->size)
        RECORD_OVERLAY_STRING (overlay, str, 0);
@@ -2819,9 +2926,7 @@ load_overlay_strings (it)
     }
       
   /* Process overlays after the overlay center.  */
-  for (ov = current_buffer->overlays_after;
-       CONSP (ov);
-       ov = XCDR (ov))
+  for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
     {
       overlay = XCAR (ov);
       xassert (OVERLAYP (overlay));
@@ -2833,7 +2938,9 @@ load_overlay_strings (it)
       
       /* Skip this overlay if it doesn't start or end at IT's current
         position.  */
-      if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
+      if (end != IT_CHARPOS (*it)
+         && start != IT_CHARPOS (*it)
+         && it->add_overlay_start != IT_CHARPOS (*it))
        continue;
 
       /* Skip this overlay if it doesn't apply to IT->w.  */
@@ -2842,7 +2949,8 @@ load_overlay_strings (it)
        continue;
       
       /* If overlay has a non-empty before-string, record it.  */
-      if (start == IT_CHARPOS (*it)
+      if ((start == IT_CHARPOS (*it)
+          || start == it->add_overlay_start)
          && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
          && XSTRING (str)->size)
        RECORD_OVERLAY_STRING (overlay, str, 0);
@@ -2857,7 +2965,8 @@ load_overlay_strings (it)
 #undef RECORD_OVERLAY_STRING
    
   /* Sort entries.  */
-  qsort (entries, n, sizeof *entries, compare_overlay_entries);
+  if (n)
+    qsort (entries, n, sizeof *entries, compare_overlay_entries);
 
   /* Record the total number of strings to process.  */
   it->n_overlay_strings = n;
@@ -2869,7 +2978,7 @@ load_overlay_strings (it)
   j = it->current.overlay_string_index;
   while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
     it->overlay_strings[i++] = entries[j++].string;
-  
+
   CHECK_IT (it);
 }
 
@@ -3056,7 +3165,8 @@ back_to_previous_visible_line_start (it)
        {
          Lisp_Object prop;
 
-         prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window);
+         prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
+                                    Qinvisible, it->window);
          if (TEXT_PROP_MEANS_INVISIBLE (prop))
            visible_p = 0;
        }
@@ -3253,7 +3363,6 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
   bzero (&it->current, sizeof it->current);
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
-  it->charset = CHARSET_ASCII;
   xassert (charpos >= 0);
   
   /* Use the setting of MULTIBYTE if specified.  */
@@ -3332,7 +3441,6 @@ get_next_display_element (it)
      function pointer `method' used here turns out to be faster than
      using a sequence of if-statements.  */
   int success_p = (*it->method) (it);
-  int charset;
 
   if (it->what == IT_CHARACTER)
     {
@@ -3417,7 +3525,7 @@ get_next_display_element (it)
              else
                {
                  unsigned char str[MAX_MULTIBYTE_LENGTH];
-                 int len = CHAR_STRING (it->c, str);
+                 int len;
                  int i;
                  GLYPH escape_glyph;
 
@@ -3429,6 +3537,11 @@ get_next_display_element (it)
                  else
                    escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
 
+                 if (SINGLE_BYTE_CHAR_P (it->c))
+                   str[0] = it->c, len = 1;
+                 else
+                   len = CHAR_STRING (it->c, str);
+
                  for (i = 0; i < len; i++)
                    {
                      XSETINT (it->ctl_chars[i * 4], escape_glyph);
@@ -3454,16 +3567,14 @@ get_next_display_element (it)
            }
        }
 
-      /* Adjust face id if charset changes.  There are no charset
-         changes in unibyte text because Emacs' charsets are not
-        applicable there.  */
+      /* Adjust face id for a multibyte character.  There are no
+         multibyte character in unibyte text.  */
       if (it->multibyte_p
          && success_p
-         && (charset = CHAR_CHARSET (it->c),
-             charset != it->charset))
+         && FRAME_WINDOW_P (it->f))
        {
-         it->charset = charset;
-         it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset);
+         struct face *face = FACE_FROM_ID (it->f, it->face_id);
+         it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
        }
     }
 
@@ -3549,11 +3660,9 @@ set_iterator_to_next (it)
         strings.  */
       ++it->current.dpvec_index;
 
-      /* Restore face and charset of the iterator to what they were
-        before the display vector entry (these entries may contain
-        faces, and of course characters of different charsets).  */
+      /* Restore face of the iterator to what they were before the
+         display vector entry (these entries may contain faces).  */
       it->face_id = it->saved_face_id;
-      it->charset = FACE_FROM_ID (it->f, it->face_id)->charset;
       
       if (it->dpvec + it->current.dpvec_index == it->dpend)
        {
@@ -3662,7 +3771,7 @@ next_element_from_display_vector (it)
 
       g = XFASTINT (it->dpvec[it->current.dpvec_index]);
       it->c = FAST_GLYPH_CHAR (g);
-      it->len = CHAR_LEN (it->c);
+      it->len = CHAR_BYTES (it->c);
 
       /* The entry may contain a face id to use.  Such a face id is
         the id of a Lisp face, not a realized face.  A face id of
@@ -3674,7 +3783,6 @@ next_element_from_display_vector (it)
          if (face_id >= 0)
            {
              it->face_id = face_id;
-             it->charset = CHARSET_ASCII;
            }
        }
     }
@@ -4699,13 +4807,13 @@ add_to_log (format, arg1, arg2)
   args[0] = fmt = build_string (format);
   args[1] = arg1;
   args[2] = arg2;
-  msg = Fformat (make_number (3), args);
+  msg = Fformat (3, args);
 
   len = STRING_BYTES (XSTRING (msg)) + 1;
   buffer = (char *) alloca (len);
   strcpy (buffer, XSTRING (msg)->data);
   
-  message_dolog (buffer, len, 1, 0);
+  message_dolog (buffer, len - 1, 1, 0);
   UNGCPRO;
 }
 
@@ -5292,6 +5400,7 @@ ensure_echo_area_buffers ()
        char name[30];
        sprintf (name, " *Echo Area %d*", i);
        echo_buffer[i] = Fget_buffer_create (build_string (name));
+       XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
       }
 }
 
@@ -5313,14 +5422,14 @@ ensure_echo_area_buffers ()
    Value is what FN returns. */
 
 static int
-with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5)
+with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
      struct window *w;
      int which;
      int (*fn) ();
-     int a1, a2, a3, a4, a5;
+     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
 {
   Lisp_Object buffer;
-  int i, this_one, the_other, clear_buffer_p, rc;
+  int this_one, the_other, clear_buffer_p, rc;
   int count = specpdl_ptr - specpdl;
 
   /* If buffers aren't life, make new ones.  */
@@ -5373,7 +5482,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5)
       w->buffer = buffer;
       set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
     }
-  current_buffer->truncate_lines = Qnil;
+
   current_buffer->undo_list = Qt;
   current_buffer->read_only = Qnil;
 
@@ -5507,11 +5616,23 @@ setup_echo_area_for_printing (multibyte_p)
          Fraise_frame  (WINDOW_FRAME (XWINDOW (mini_window)));
        }
 
+      message_log_maybe_newline ();
       message_buf_print = 1;
     }
-  else if (current_buffer != XBUFFER (echo_area_buffer[0]))
-    /* Someone switched buffers between print requests.  */
-    set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+  else
+    {
+      if (NILP (echo_area_buffer[0]))
+       {
+         if (EQ (echo_area_buffer[1], echo_buffer[0]))
+           echo_area_buffer[0] = echo_buffer[1]; 
+         else
+           echo_area_buffer[0] = echo_buffer[0];
+       }
+      
+      if (current_buffer != XBUFFER (echo_area_buffer[0]))
+       /* Someone switched buffers between print requests.  */
+       set_buffer_internal (XBUFFER (echo_area_buffer[0]));
+    }
 }
 
 
@@ -5524,7 +5645,14 @@ static int
 display_echo_area (w)
      struct window *w;
 {
-  int i, no_message_p, window_height_changed_p;
+  int i, no_message_p, window_height_changed_p, count;
+
+  /* Temporarily disable garbage collections while displaying the echo
+     area.  This is done because a GC can print a message itself.
+     That message would modify the echo area buffer's contents while a
+     redisplay of the buffer is going on, and seriously confuse
+     redisplay.  */
+  count = inhibit_garbage_collection ();
 
   /* If there is no message, we must call display_echo_area_1
      nevertheless because it resizes the window.  But we will have to
@@ -5539,7 +5667,8 @@ display_echo_area (w)
 
   if (no_message_p)
     echo_area_buffer[i] = Qnil;
-  
+
+  unbind_to (count, Qnil);
   return window_height_changed_p;
 }
 
@@ -5640,13 +5769,19 @@ resize_mini_window (w, exact_p)
       max_height = min (total_height, max_height);
       
       /* Find out the height of the text in the window.  */
-      last_height = 0;
-      move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
-      if (it.max_ascent == 0 && it.max_descent == 0)
-       height = it.current_y + last_height;
+      if (it.truncate_lines_p)
+       height = 1;
       else
-       height = it.current_y + it.max_ascent + it.max_descent;
-      height = (height + unit - 1) / unit;
+       {
+         last_height = 0;
+         move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
+         if (it.max_ascent == 0 && it.max_descent == 0)
+           height = it.current_y + last_height;
+         else
+           height = it.current_y + it.max_ascent + it.max_descent;
+         height -= it.extra_line_spacing;
+         height = (height + unit - 1) / unit;
+       }
       
       /* Compute a suitable window start.  */
       if (height > max_height)
@@ -5850,6 +5985,8 @@ set_message_1 (s, string, nbytes, multibyte_p)
       != !NILP (current_buffer->enable_multibyte_characters))
     Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
 
+  current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
+  
   /* Insert new message at BEG.  */
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
 
@@ -5983,14 +6120,14 @@ echo_area_display (update_frame_p)
   if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
     return 0;
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   /* When Emacs starts, selected_frame may be a visible terminal
      frame, even if we run under a window system.  If we let this
      through, a message would be displayed on the terminal.  */
   if (EQ (selected_frame, Vterminal_frame) 
       && !NILP (Vwindow_system))
     return 0;
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
 
   /* Redraw garbaged frames.  */
   if (frame_garbaged)
@@ -6485,7 +6622,8 @@ build_desired_tool_bar_string (f)
 
   /* Reuse f->desired_tool_bar_string, if possible.  */
   if (size < size_needed)
-    f->desired_tool_bar_string = Fmake_string (make_number (size_needed), ' ');
+    f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
+                                              make_number (' '));
   else
     {
       props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
@@ -6922,9 +7060,16 @@ static int
 hscroll_windows (window)
      Lisp_Object window;
 {
-  int hscrolled_p = hscroll_window_tree (window);
-  if (hscrolled_p)
-    clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
+  int hscrolled_p;
+  
+  if (automatic_hscrolling_p)
+    {
+      hscrolled_p = hscroll_window_tree (window);
+      if (hscrolled_p)
+       clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
+    }
+  else
+    hscrolled_p = 0;
   return hscrolled_p;
 }
 
@@ -7137,9 +7282,9 @@ reconsider_clip_changes (w, b)
        pt = marker_position (w->pointm);
 
       if ((w->current_matrix->buffer != XBUFFER (w->buffer)
-          || pt != w->last_point)
+          || pt != XINT (w->last_point))
          && check_point_in_composition (w->current_matrix->buffer,
-                                        w->last_point,
+                                        XINT (w->last_point),
                                         XBUFFER (w->buffer), pt))
        b->clip_changed = 1;
     }
@@ -7461,10 +7606,10 @@ redisplay_internal (preserve_echo_area)
                                     - MATRIX_ROW_START_BYTEPOS (row));
                    }
   
-                 increment_glyph_matrix_buffer_positions (w->current_matrix,
-                                                          this_line_vpos + 1,
-                                                          w->current_matrix->nrows,
-                                                          delta, delta_bytes);
+                 increment_matrix_positions (w->current_matrix,
+                                             this_line_vpos + 1,
+                                             w->current_matrix->nrows,
+                                             delta, delta_bytes);
                }
 
              /* If this row displays text now but previously didn't,
@@ -7772,7 +7917,7 @@ update:
          w->current_matrix->begv = BUF_BEGV (b);
          w->current_matrix->zv = BUF_ZV (b);
        }
-      
+
       update_mode_lines = 0;
       windows_or_buffers_changed = 0;
     }
@@ -7915,9 +8060,9 @@ mark_window_display_accurate (window, accurate_p)
              w->last_cursor = w->cursor;
              w->last_cursor_off_p = w->cursor_off_p;
              if (w == XWINDOW (selected_window))
-               w->last_point = BUF_PT (b);
+               w->last_point = make_number (BUF_PT (b));
              else
-               w->last_point = XMARKER (w->pointm)->charpos;
+               w->last_point = make_number (XMARKER (w->pointm)->charpos);
            }
        }
 
@@ -7962,7 +8107,7 @@ disp_char_vector (dp, c)
   if (SINGLE_BYTE_CHAR_P (c))
     return (dp->contents[c]);
   
-  SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
+  SPLIT_CHAR (c, code[0], code[1], code[2]);
   if (code[1] < 32)
     code[1] = -1;
   else if (code[2] < 32)
@@ -8036,7 +8181,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
      frames.  */
   if (row->displays_text_p)
     while (glyph < end
-          && !glyph->object
+          && INTEGERP (glyph->object)
           && glyph->charpos < 0)
       {
        x += glyph->pixel_width;
@@ -8044,7 +8189,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       }
 
   while (glyph < end
-        && glyph->object
+        && !INTEGERP (glyph->object)
         && (!BUFFERP (glyph->object)
             || glyph->charpos < pt_old))
     {
@@ -8135,21 +8280,24 @@ make_cursor_line_fully_visible (w)
   matrix = w->desired_matrix;
   row = MATRIX_ROW (matrix, w->cursor.vpos);
 
-  /* If row->y == top y of window display area, the window isn't tall
-     enough to display a single line.  There is nothing we can do
-     about it.  */
-  header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-  if (row->y == header_line_height)
-    return;
-
-  if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
+  if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)
+      /* The row may be partially visible at the top because we
+        already have chosen a vscroll to align the bottom of the
+        row with the bottom of the window.  This happens for rows
+        taller than the window.  */
+      && row->y + row->height < window_box_height (w))
     {
       int dy = row->height - row->visible_height;
       w->vscroll = 0;
       w->cursor.y += dy;
       shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
     }
-  else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
+  else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)
+          /* The row may be partially visible at the bottom because
+             we chose a vscroll to align the row's top with the
+             window's top.  This happens for rows taller than the
+             window.  */
+          && row->y > WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w))
     {
       int dy = - (row->height - row->visible_height);
       w->vscroll = dy;
@@ -8470,7 +8618,6 @@ redisplay_window (window, just_this_one_p)
   struct it it;
   /* Record it now because it's overwritten.  */
   int current_matrix_up_to_date_p = 0;
-  int really_switched_buffer = 0;
   int temp_scroll_step = 0;
   int count = specpdl_ptr - specpdl;
 
@@ -8523,15 +8670,9 @@ redisplay_window (window, just_this_one_p)
 
   /* Otherwise set up data on this window; select its buffer and point
      value.  */
-  if (update_mode_line)
-    {
-      /* Really select the buffer, for the sake of buffer-local
-         variables.  */
-      set_buffer_internal_1 (XBUFFER (w->buffer));
-      really_switched_buffer = 1;
-    }
-  else
-    set_buffer_temp (XBUFFER (w->buffer));
+  /* Really select the buffer, for the sake of buffer-local
+     variables.  */
+  set_buffer_internal_1 (XBUFFER (w->buffer));
   SET_TEXT_POS (opoint, PT, PT_BYTE);
 
   current_matrix_up_to_date_p
@@ -8671,13 +8812,6 @@ redisplay_window (window, just_this_one_p)
       if (!update_mode_line
          || ! NILP (Vwindow_scroll_functions))
        {
-         if (!really_switched_buffer)
-           {
-             set_buffer_temp (old);
-             set_buffer_internal_1 (XBUFFER (w->buffer));
-             really_switched_buffer = 1;
-           }
-         
          update_mode_line = 1;
          w->update_mode_line = Qt;
          startp = run_window_scroll_functions (window, startp);
@@ -8810,20 +8944,26 @@ redisplay_window (window, just_this_one_p)
          /* Point has moved forward.  */
          int last_y = window_text_bottom_y (w) - this_scroll_margin;
          
-         while ((MATRIX_ROW_END_CHARPOS (row) < PT
-                 /* The end position of a row equals the start
-                    position of the next row.  If PT is there, we
-                    would rather display it in the next line, except
-                    when this line ends in ZV.  */
-                 || (MATRIX_ROW_END_CHARPOS (row) == PT
-                     && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
-                         || !row->ends_at_zv_p)))
+         while (MATRIX_ROW_END_CHARPOS (row) < PT
                 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
            {
              xassert (row->enabled_p);
              ++row;
            }
 
+         /* The end position of a row equals the start position of
+            the next row.  If PT is there, we would rather display it
+            in the next line.  Exceptions are when the row ends in
+            the middle of a character, or ends in ZV.  */
+         if (MATRIX_ROW_BOTTOM_Y (row) < last_y
+             && MATRIX_ROW_END_CHARPOS (row) == PT
+             && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+             && !row->ends_at_zv_p)
+           {
+             xassert (row->enabled_p);
+             ++row;
+           }
+
          /* If within the scroll margin, scroll.  Note that
             MATRIX_ROW_BOTTOM_Y gives the pixel position at which the
             next line would be drawn, and that this_scroll_margin can
@@ -8970,7 +9110,8 @@ redisplay_window (window, just_this_one_p)
          If point has not moved off frame, accept the results.  */
       if (!current_matrix_up_to_date_p
          /* Don't use try_window_reusing_current_matrix in this case
-            because it can have changed the buffer.  */
+            because a window scroll function can have changed the
+            buffer.  */
          || !NILP (Vwindow_scroll_functions)
          || MINI_WINDOW_P (w)
          || !try_window_reusing_current_matrix (w))
@@ -9005,12 +9146,6 @@ redisplay_window (window, just_this_one_p)
   /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
     {
-      if (!really_switched_buffer)
-       {
-         set_buffer_temp (old);
-         set_buffer_internal_1 (XBUFFER (w->buffer));
-         really_switched_buffer = 1;
-       }
       update_mode_line = 1;
       w->update_mode_line = Qt;
     }
@@ -9162,7 +9297,13 @@ redisplay_window (window, just_this_one_p)
        && (WINDOW_WANTS_MODELINE_P (w)
           || WINDOW_WANTS_HEADER_LINE_P (w)))
     {
+      Lisp_Object old_selected_frame;
+      
+      old_selected_frame = selected_frame;
+      
+      XSETFRAME (selected_frame, f);
       display_mode_lines (w);
+      selected_frame = old_selected_frame;
 
       /* If mode line height has changed, arrange for a thorough
         immediate redisplay using the correct mode line height.  */
@@ -9268,10 +9409,7 @@ redisplay_window (window, just_this_one_p)
 
   /* Restore current_buffer and value of point in it.  */
   TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
-  if (really_switched_buffer)
-    set_buffer_internal_1 (old);
-  else
-    set_buffer_temp (old);
+  set_buffer_internal_1 (old);
   TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
 
   unbind_to (count, Qnil);
@@ -9369,8 +9507,12 @@ try_window_reusing_current_matrix (w)
   struct glyph_row *start_row;
   int start_vpos, min_y, max_y;
 
-  /* Right now this function doesn't handle terminal frames.  */
-  if (!FRAME_WINDOW_P (f))
+  
+  if (/* This function doesn't handle terminal frames.  */
+      !FRAME_WINDOW_P (f)
+      /* Don't try to reuse the display if windows have been split
+        or such.  */
+      || windows_or_buffers_changed)
     return 0;
 
   /* Can't do this if region may have changed.  */
@@ -9467,7 +9609,8 @@ try_window_reusing_current_matrix (w)
          run.current_y = first_row_y;
          run.desired_y = it.current_y;
          run.height = it.last_visible_y - it.current_y;
-         if (run.height > 0)
+         if (run.height > 0
+             && run.current_y != run.desired_y)
            {
              update_begin (f);
              rif->update_window_begin_hook (w);
@@ -10029,7 +10172,9 @@ try_window_id (w)
      only if buffer has really changed.  The reason is that the gap is
      initially at Z for freshly visited files.  The code below would
      set end_unchanged to 0 in that case.  */
-  if (MODIFF > SAVE_MODIFF)
+  if (MODIFF > SAVE_MODIFF
+      /* This seems to happen sometimes after saving a buffer.  */
+      || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
     {
       if (GPT - BEG < BEG_UNCHANGED)
        BEG_UNCHANGED = GPT - BEG;
@@ -10037,25 +10182,40 @@ try_window_id (w)
        END_UNCHANGED = Z - GPT;
     }
 
-  /* Some strange bug seems to be causing that to happen sometimes.  */
-  if (BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
-    abort ();
-  
   /* If window starts after a line end, and the last change is in
      front of that newline, then changes don't affect the display.
-     This case happens with stealth-fontification.  */
+     This case happens with stealth-fontification.  Note that although
+     the display is unchanged, glyph positions in the matrix have to
+     be adjusted, of course.  */
   row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
   if (CHARPOS (start) > BEGV
       && Z - END_UNCHANGED < CHARPOS (start) - 1
       && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
       && PT < MATRIX_ROW_END_CHARPOS (row))
     {
-      /* We have to update window end positions because the buffer's
-        size has changed.  */
+      struct glyph_row *r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
+      int delta = CHARPOS (start) - MATRIX_ROW_START_CHARPOS (r0);
+
+      if (delta)
+       {
+         struct glyph_row *r1 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
+         int delta_bytes = BYTEPOS (start) - MATRIX_ROW_START_BYTEPOS (r0);
+
+         increment_matrix_positions (w->current_matrix,
+                                     MATRIX_ROW_VPOS (r0, current_matrix),
+                                     MATRIX_ROW_VPOS (r1, current_matrix),
+                                     delta, delta_bytes);
+       }
+      
+#if 0  /* If changes are all in front of the window start, the
+         distance of the last displayed glyph from Z hasn't
+         changed.  */
       w->window_end_pos
        = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
       w->window_end_bytepos
-       = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
+       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+#endif
+
       return 1;
     }
 
@@ -10069,7 +10229,7 @@ try_window_id (w)
       w->window_end_pos
        = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
       w->window_end_bytepos
-       = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
+       = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       return 1;
     }
 
@@ -10284,7 +10444,7 @@ try_window_id (w)
   /* Scroll the display.  Do it before changing the current matrix so
      that xterm.c doesn't get confused about where the cursor glyph is
      found.  */
-  if (dy)
+  if (dy && run.height)
     {
       update_begin (f);
          
@@ -10370,9 +10530,9 @@ try_window_id (w)
 
   /* Adjust buffer positions in reused rows.  */
   if (delta)
-    increment_glyph_matrix_buffer_positions (current_matrix,
-                                            first_unchanged_at_end_vpos + dvpos,
-                                            bottom_vpos, delta, delta_bytes);
+    increment_matrix_positions (current_matrix,
+                               first_unchanged_at_end_vpos + dvpos,
+                               bottom_vpos, delta, delta_bytes);
 
   /* Adjust Y positions.  */
   if (dy)
@@ -10519,7 +10679,7 @@ static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
 /* Dump the contents of glyph matrix MATRIX on stderr.  If
    WITH_GLYPHS_P is non-zero, dump glyph contents as well.  */
 
-void
+static void
 dump_glyph_matrix (matrix, with_glyphs_p)
      struct glyph_matrix *matrix;
      int with_glyphs_p;
@@ -10545,10 +10705,10 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
 
   row = MATRIX_ROW (matrix, vpos);
   
-  fprintf (stderr, "Row Start   End Used oEI><O\\CTZF    X   Y   W\n");
+  fprintf (stderr, "Row Start   End Used oEI><O\\CTZFes    X   Y   W\n");
   fprintf (stderr, "=============================================\n");
   
-  fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d\n",
+  fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d\n",
           row - matrix->rows,
           MATRIX_ROW_START_CHARPOS (row),
           MATRIX_ROW_END_CHARPOS (row),
@@ -10564,6 +10724,8 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
           row->displays_text_p,
           row->ends_at_zv_p,
           row->fill_line_p,
+          row->ends_in_middle_of_char_p,
+          row->starts_in_middle_of_char_p,
           row->x,
           row->y,
           row->pixel_width);
@@ -10589,7 +10751,7 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
       
       if (glyph < glyph_end)
        {
-         fprintf (stderr, "  Glyph    Type Pos   W    Code C Face LR\n");
+         fprintf (stderr, "  Glyph    Type Pos   W    Code C Face LR\n");
          prev_had_glyphs_p = 1;
        }
       else
@@ -10600,10 +10762,15 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
          if (glyph->type == CHAR_GLYPH)
            {
              fprintf (stderr,
-                      "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+                      "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
                       glyph - row->glyphs[TEXT_AREA],
                       'C',
                       glyph->charpos,
+                      (BUFFERP (glyph->object)
+                       ? 'B'
+                       : (STRINGP (glyph->object)
+                          ? 'S'
+                          : '-')),
                       glyph->pixel_width,
                       glyph->u.ch,
                       (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
@@ -10616,10 +10783,15 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
          else if (glyph->type == STRETCH_GLYPH)
            {
              fprintf (stderr,
-                      "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+                      "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
                       glyph - row->glyphs[TEXT_AREA],
                       'S',
                       glyph->charpos,
+                      (BUFFERP (glyph->object)
+                       ? 'B'
+                       : (STRINGP (glyph->object)
+                          ? 'S'
+                          : '-')),
                       glyph->pixel_width,
                       0,
                       '.',
@@ -10630,10 +10802,15 @@ dump_glyph_row (matrix, vpos, with_glyphs_p)
          else if (glyph->type == IMAGE_GLYPH)
            {
              fprintf (stderr,
-                      "  %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
+                      "  %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
                       glyph - row->glyphs[TEXT_AREA],
                       'I',
                       glyph->charpos,
+                      (BUFFERP (glyph->object)
+                       ? 'B'
+                       : (STRINGP (glyph->object)
+                          ? 'S'
+                          : '-')),
                       glyph->pixel_width,
                       glyph->u.img_id,
                       '.',
@@ -10653,6 +10830,7 @@ DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
 Shows contents of glyph row structures.  With non-nil optional\n\
 parameter WITH-GLYPHS-P, dump glyphs as well.")
   (with_glyphs_p)
+     Lisp_Object with_glyphs_p;
 {
   struct window *w = XWINDOW (selected_window);
   struct buffer *buffer = XBUFFER (w->buffer);
@@ -10795,13 +10973,12 @@ insert_left_trunc_glyphs (it)
 
   /* Get the truncation glyphs.  */
   truncate_it = *it;
-  truncate_it.charset = -1;
   truncate_it.current_x = 0;
   truncate_it.face_id = DEFAULT_FACE_ID;
   truncate_it.glyph_row = &scratch_glyph_row;
   truncate_it.glyph_row->used[TEXT_AREA] = 0;
   CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
-  truncate_it.object = 0;
+  truncate_it.object = make_number (0);
   produce_special_glyphs (&truncate_it, IT_TRUNCATION);
   
   /* Overwrite glyphs from IT with truncation glyphs.  */
@@ -10951,25 +11128,22 @@ append_space (it, default_face_p)
          struct text_pos saved_pos;
          int saved_what = it->what;
          int saved_face_id = it->face_id;
-         int saved_charset = it->charset;
          Lisp_Object saved_object;
+         struct face *face;
 
          saved_object = it->object;
          saved_pos = it->position;
          
          it->what = IT_CHARACTER;
          bzero (&it->position, sizeof it->position);
-         it->object = 0;
+         it->object = make_number (0);
          it->c = ' ';
          it->len = 1;
-         it->charset = CHARSET_ASCII;
 
          if (default_face_p)
            it->face_id = DEFAULT_FACE_ID;
-         if (it->multibyte_p)
-           it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII);
-         else
-           it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1);
+         face = FACE_FROM_ID (it->f, it->face_id);
+         it->face_id = FACE_FOR_CHAR (it->f, face, 0);
 
          PRODUCE_GLYPHS (it);
          
@@ -10978,7 +11152,6 @@ append_space (it, default_face_p)
          it->position = saved_pos;
          it->what = saved_what;
          it->face_id = saved_face_id;
-         it->charset = saved_charset;
          return 1;
        }
     }
@@ -11017,15 +11190,13 @@ extend_face_to_end_of_line (it)
      in the text area has to be drawn to the end of the text area.  */
   it->glyph_row->fill_line_p = 1;
 
-  /* If current charset of IT is not ASCII, make sure we have the
-     ASCII face.  This will be automatically undone the next time
-     get_next_display_element returns a character from a different
-     charset.  Note that the charset will always be ASCII in unibyte
-     text.  */
-  if (it->charset != CHARSET_ASCII)
+  /* If current character of IT is not ASCII, make sure we have the
+         ASCII face.  This will be automatically undone the next time
+         get_next_display_element returns a multibyte character.  Note
+         that the character will always be single byte in unibyte text.  */
+  if (!SINGLE_BYTE_CHAR_P (it->c))
     {
-      it->charset = CHARSET_ASCII;
-      it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII);
+      it->face_id = FACE_FOR_CHAR (f, face, 0);
     }
 
   if (FRAME_WINDOW_P (f))
@@ -11052,7 +11223,7 @@ extend_face_to_end_of_line (it)
   
       it->what = IT_CHARACTER;
       bzero (&it->position, sizeof it->position);
-      it->object = 0;
+      it->object = make_number (0);
       it->c = ' ';
       it->len = 1;
       
@@ -11113,7 +11284,7 @@ highlight_trailing_whitespace (f, row)
         cursor at the end of a line.  */
       if (glyph->type == CHAR_GLYPH
          && glyph->u.ch == ' '
-         && glyph->object == 0)
+         && INTEGERP (glyph->object))
        --glyph;
 
       /* If last glyph is a space or stretch, and it's trailing
@@ -11126,8 +11297,7 @@ highlight_trailing_whitespace (f, row)
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
-         int face_id = lookup_named_face (f, Qtrailing_whitespace,
-                                          CHARSET_ASCII);
+         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
          
          while (glyph >= start
                 && BUFFERP (glyph->object)
@@ -11169,6 +11339,8 @@ display_line (it)
   row->start = it->current;
   row->continuation_lines_width = it->continuation_lines_width;
   row->displays_text_p = 1;
+  row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
+  it->starts_in_middle_of_char_p = 0;
 
   /* Arrange the overlays nicely for our purposes.  Usually, we call
      display_line on only one line at a time, in which case this
@@ -11197,6 +11369,7 @@ display_line (it)
     {
       int n_glyphs_before, hpos_before, x_before;
       int x, i, nglyphs;
+      int ascent, descent, phys_ascent, phys_descent;
       
       /* Retrieve the next thing to display.  Value is zero if end of
         buffer reached.  */
@@ -11225,6 +11398,17 @@ display_line (it)
         generates glyphs in `row' (which is IT->glyph_row).  */
       n_glyphs_before = row->used[TEXT_AREA];
       x = it->current_x;
+
+      /* Remember the line height so far in case the next element doesn't
+        fit on the line.  */
+      if (!it->truncate_lines_p)
+       {
+         ascent = it->max_ascent;
+         descent = it->max_descent;
+         phys_ascent = it->max_phys_ascent;
+         phys_descent = it->max_phys_descent;
+       }
+      
       PRODUCE_GLYPHS (it);
 
       /* If this display element was in marginal areas, continue with
@@ -11289,9 +11473,10 @@ display_line (it)
                      || (new_x == it->last_visible_x
                          && FRAME_WINDOW_P (it->f)))
                    {
-                     /* Current glyph fits exactly on the line.  We
-                        must continue the line because we can't draw
-                        the cursor after the glyph.  */
+                     /* Current glyph is the only one on the line or
+                        fits exactly on the line.  We must continue
+                        the line because we can't draw the cursor
+                        after the glyph.  */
                      row->continued_p = 1;
                      it->current_x = new_x;
                      it->continuation_lines_width += new_x;
@@ -11299,6 +11484,31 @@ display_line (it)
                      if (i == nglyphs - 1)
                        set_iterator_to_next (it);
                    }
+                 else if (CHAR_GLYPH_PADDING_P (*glyph)
+                          && !FRAME_WINDOW_P (it->f))
+                   {
+                     /* A padding glyph that doesn't fit on this line.
+                        This means the whole character doesn't fit
+                        on the line.  */
+                     row->used[TEXT_AREA] = n_glyphs_before;
+                 
+                     /* Fill the rest of the row with continuation
+                        glyphs like in 20.x.  */
+                     while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
+                            < row->glyphs[1 + TEXT_AREA])
+                       produce_special_glyphs (it, IT_CONTINUATION);
+                     
+                     row->continued_p = 1;
+                     it->current_x = x_before;
+                     it->continuation_lines_width += x_before;
+                     
+                     /* Restore the height to what it was before the
+                        element not fitting on the line.  */
+                     it->max_ascent = ascent;
+                     it->max_descent = descent;
+                     it->max_phys_ascent = phys_ascent;
+                     it->max_phys_descent = phys_descent;
+                   }
                  else
                    {
                      /* Display element draws past the right edge of
@@ -11315,7 +11525,20 @@ display_line (it)
                      
                      it->current_x = x;
                      it->continuation_lines_width += x;
+                     if (nglyphs > 1 && i > 0)
+                       {
+                         row->ends_in_middle_of_char_p = 1;
+                         it->starts_in_middle_of_char_p = 1;
+                       }
+                     
+                     /* Restore the height to what it was before the
+                        element not fitting on the line.  */
+                     it->max_ascent = ascent;
+                     it->max_descent = descent;
+                     it->max_phys_ascent = phys_ascent;
+                     it->max_phys_descent = phys_descent;
                    }
+
                  break;
                }
              else if (new_x > it->first_visible_x)
@@ -11458,16 +11681,20 @@ display_line (it)
   /* Remember the position at which this line ends.  */
   row->end = it->current;
 
-  /* Maybe set the cursor.  If you change this, it's probably a good
-     idea to also change the code in redisplay_window for cursor
-     movement in an unchanged window.  */
+  /* Maybe set the cursor.  */
   if (it->w->cursor.vpos < 0
       && PT >= MATRIX_ROW_START_CHARPOS (row)
-      && MATRIX_ROW_END_CHARPOS (row) >= PT
-      && !(MATRIX_ROW_END_CHARPOS (row) == PT
-          && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
-              || !row->ends_at_zv_p)))
-    set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
+      && PT <= MATRIX_ROW_END_CHARPOS (row))
+    {
+      /* Also see redisplay_window, case cursor movement in unchanged
+        window.  */
+      if (MATRIX_ROW_END_CHARPOS (row) == PT
+         && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
+         && !row->ends_at_zv_p)
+       ;
+      else
+       set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
+    }
 
   /* Highlight trailing whitespace.  */
   if (!NILP (Vshow_trailing_whitespace))
@@ -11993,9 +12220,9 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
   /* The EOL conversion we are using.  */
   Lisp_Object eoltype;
 
-  val = coding_system;
+  val = Fget (coding_system, Qcoding_system);
 
-  if (NILP (val))              /* Not yet decided.  */
+  if (!VECTORP (val))          /* Not yet decided.  */
     {
       if (multibyte)
        *buf++ = '-';
@@ -12009,13 +12236,6 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 
       eolvalue = Fget (coding_system, Qeol_type);
 
-      while (!NILP (val) && SYMBOLP (val))
-       {
-         val = Fget (val, Qcoding_system);
-         if (NILP (eolvalue))
-           eolvalue = Fget (val, Qeol_type);
-       }
-
       if (multibyte)
        *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
 
@@ -12046,6 +12266,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
       else if (INTEGERP (eoltype)
               && CHAR_VALID_P (XINT (eoltype), 0))
        {
+         eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
          eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
        }
       else
@@ -12192,7 +12413,8 @@ decode_mode_spec (w, c, field_width, precision)
          w->base_line_pos = Qnil;
 
        /* If the buffer is very big, don't waste time.  */
-       if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
+       if (INTEGERP (Vline_number_display_limit)
+           && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
          {
            w->base_line_pos = Qnil;
            w->base_line_number = Qnil;
@@ -12279,7 +12501,8 @@ decode_mode_spec (w, c, field_width, precision)
          while (pad-- > 0)
            *p++ = ' ';
          *p++ = '?';
-         *p = '?';
+         *p++ = '?';
+         *p = '\0';
          return decode_mode_spec_buf;
        }
       }
@@ -12840,6 +13063,8 @@ syms_of_xdisp ()
   staticpro (&Qinhibit_point_motion_hooks);
   Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
 
+  QCdata = intern (":data");
+  staticpro (&QCdata);
   Qdisplay = intern ("display");
   staticpro (&Qdisplay);
   Qspace_width = intern ("space-width");
@@ -12878,6 +13103,8 @@ syms_of_xdisp ()
   staticpro (&Qtrailing_whitespace);
   Qimage = intern ("image");
   staticpro (&Qimage);
+  Qmessage_truncate_lines = intern ("message-truncate-lines");
+  staticpro (&Qmessage_truncate_lines);
 
   last_arrow_position = Qnil;
   last_arrow_string = Qnil;
@@ -12946,13 +13173,14 @@ of the top or bottom of the window.");
     "*Non-nil means use inverse video for the mode line.");
   mode_line_inverse_video = 1;
 
-  DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
+  DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
     "*Maximum buffer size for which line number should be displayed.\n\
 If the buffer is bigger than this, the line number does not appear\n\
-in the mode line.");
-  line_number_display_limit = 1000000;
+in the mode line.  A value of nil means no limit.");
+  Vline_number_display_limit = Qnil;
 
-  DEFVAR_INT ("line-number-display-limit-width", &line_number_display_limit_width,
+  DEFVAR_INT ("line-number-display-limit-width",
+             &line_number_display_limit_width,
     "*Maximum line width (in characters) for line number display.\n\
 If the average length of the lines near point is bigger than this, then the\n\
 line number may be omitted from the mode line.");
@@ -13055,6 +13283,26 @@ If a float, it specifies a fraction of the mini-window frame's height.\n\
 If an integer, it specifies a number of lines.\n\
 If nil, don't resize.");
   Vmax_mini_window_height = make_float (0.25);
+  
+  DEFVAR_BOOL ("cursor-in-non-selected-windows",
+              &cursor_in_non_selected_windows,
+    "*Non-nil means display a hollow cursor in non-selected windows.\n\
+Nil means don't display a cursor there.");
+  cursor_in_non_selected_windows = 1;
+  
+  DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p,
+    "*Non-nil means scroll the display automatically to make point visible.");
+  automatic_hscrolling_p = 1;
+  
+  DEFVAR_LISP ("image-types", &Vimage_types,
+    "List of supported image types.\n\
+Each element of the list is a symbol for a supported image type.");
+  Vimage_types = Qnil;
+  
+  DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
+    "If non-nil, messages are truncated instead of resizing the echo area.\n\
+Bind this around calls to `message' to let it take effect.");
+  message_truncate_lines = 0;
 }