(run-python): Remove '' from sys.path.
[bpt/emacs.git] / src / xdisp.c
index 9f0c173..89dc814 100644 (file)
@@ -167,6 +167,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
+#include <limits.h>
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -196,13 +197,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef WINDOWSNT
 #include "w32term.h"
 #endif
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
+#endif
+#ifdef USE_GTK
+#include "gtkutil.h"
 #endif
 
-#ifdef HAVE_WINDOW_SYSTEM
 #include "font.h"
-#endif /* HAVE_WINDOW_SYSTEM */
 
 #ifndef FRAME_X_OUTPUT
 #define FRAME_X_OUTPUT(f) ((f)->output_data.x)
@@ -210,8 +212,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define INFINITY 10000000
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined(HAVE_NS) || defined (USE_GTK)
 extern void set_frame_menubar P_ ((struct frame *f, int, int));
 extern int pending_menu_activation;
 #endif
@@ -264,6 +266,9 @@ Lisp_Object Qfontification_functions;
    cursor moves into it.  */
 Lisp_Object Vmouse_autoselect_window;
 
+Lisp_Object Vwrap_prefix, Qwrap_prefix;
+Lisp_Object Vline_prefix, Qline_prefix;
+
 /* Non-zero means draw tool bar buttons raised when the mouse moves
    over them.  */
 
@@ -345,10 +350,17 @@ extern Lisp_Object Voverflow_newline_into_fringe;
   (!NILP (Voverflow_newline_into_fringe)       \
    && FRAME_WINDOW_P (it->f)                   \
    && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0    \
-   && it->current_x == it->last_visible_x)
+   && it->current_x == it->last_visible_x      \
+   && it->line_wrap != WORD_WRAP)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
+/* Test if the display element loaded in IT is a space or tab
+   character.  This is used to determine word wrapping.  */
+
+#define IT_DISPLAYING_WHITESPACE(it)                           \
+  (it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t'))
+
 /* Non-nil means show the text cursor in void text areas
    i.e. in blank areas after eol and eob.  This used to be
    the default in 21.3.  */
@@ -422,7 +434,7 @@ static struct buffer *this_line_buffer;
 /* Nonzero means truncate lines in all windows less wide than the
    frame.  */
 
-int truncate_partial_width_windows;
+Lisp_Object Vtruncate_partial_width_windows;
 
 /* A flag to control how to display unibyte 8-bit character.  */
 
@@ -630,7 +642,7 @@ int message_truncate_lines;
 Lisp_Object Qmessage_truncate_lines;
 
 /* Set to 1 in clear_message to make redisplay_internal aware
-   of an emptied echo area.   */
+   of an emptied echo area.  */
 
 static int message_cleared_p;
 
@@ -717,6 +729,12 @@ struct buffer *displayed_buffer;
 
 EMACS_INT overline_margin;
 
+/* Require underline to be at least this many screen pixels below baseline
+   This to avoid underline "merging" with the base of letters at small
+   font sizes, particularly when x_use_underline_position_properties is on. */
+
+EMACS_INT underline_minimum_offset;
+
 /* Value returned from text property handlers (see below).  */
 
 enum prop_handled
@@ -838,6 +856,25 @@ Lisp_Object previous_help_echo_string;
 
 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 
+/* Platform-independent portion of hourglass implementation. */
+
+/* Non-zero means we're allowed to display a hourglass pointer.  */
+int display_hourglass_p;
+
+/* Non-zero means an hourglass cursor is currently shown.  */
+int hourglass_shown_p;
+
+/* If non-null, an asynchronous timer that, when it expires, displays
+   an hourglass cursor on all frames.  */
+struct atimer *hourglass_atimer;
+
+/* Number of seconds to wait before displaying an hourglass cursor.  */
+Lisp_Object Vhourglass_delay;
+
+/* Default number of seconds to wait before displaying an hourglass
+   cursor.  */
+#define DEFAULT_HOURGLASS_DELAY 1
+
 \f
 /* Function prototypes.  */
 
@@ -849,9 +886,9 @@ static int cursor_row_p P_ ((struct window *, struct glyph_row *));
 static int redisplay_mode_lines P_ ((Lisp_Object, int));
 static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
 
-#if 0
-static int invisible_text_between_p P_ ((struct it *, int, int));
-#endif
+static Lisp_Object get_it_property P_ ((struct it *it, Lisp_Object prop));
+
+static void handle_line_prefix P_ ((struct it *));
 
 static void pint2str P_ ((char *, int, int));
 static void pint2hrstr P_ ((char *, int, int));
@@ -941,8 +978,9 @@ static int 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 enum move_it_result move_it_in_display_line_to P_ ((struct it *,
-                                                          int, int, int));
+static enum move_it_result
+       move_it_in_display_line_to (struct it *, EMACS_INT, int,
+                                  enum move_operation_enum);
 void move_it_vertically_backward P_ ((struct it *, int));
 static void init_to_row_start P_ ((struct it *, struct window *,
                                   struct glyph_row *));
@@ -1719,9 +1757,7 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
    text, or we can't tell because W's current matrix is not up to
    date.  */
 
-#ifndef HAVE_CARBON
 static
-#endif
 struct glyph *
 x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area)
      struct window *w;
@@ -2058,7 +2094,7 @@ get_phys_cursor_geometry (w, row, glyph, xp, yp, heightp)
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
   wd = glyph->pixel_width - 1;
-#ifdef HAVE_NTGUI
+#if defined(HAVE_NTGUI) || defined(HAVE_NS)
   wd++; /* Why? */
 #endif
 
@@ -2493,6 +2529,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
      enum face_id base_face_id;
 {
   int highlight_region_p;
+  enum face_id remapped_base_face_id = base_face_id;
 
   /* Some precondition checks.  */
   xassert (w != NULL && it != NULL);
@@ -2509,6 +2546,10 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
       free_all_realized_faces (Qnil);
     }
 
+  /* Perhaps remap BASE_FACE_ID to a user-specified alternative.  */
+  if (! NILP (Vface_remapping_alist))
+    remapped_base_face_id = lookup_basic_face (XFRAME (w->frame), base_face_id);
+
   /* Use one of the mode line rows of W's desired matrix if
      appropriate.  */
   if (row == NULL)
@@ -2524,7 +2565,7 @@ 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->base_face_id = base_face_id;
+  it->base_face_id = remapped_base_face_id;
   it->string = Qnil;
   IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
 
@@ -2624,19 +2665,27 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
     it->tab_width = 8;
 
   /* Are lines in the display truncated?  */
-  it->truncate_lines_p
-    = (base_face_id != DEFAULT_FACE_ID
-       || XINT (it->w->hscroll)
-       || (truncate_partial_width_windows
-          && !WINDOW_FULL_WIDTH_P (it->w))
-       || !NILP (current_buffer->truncate_lines));
+  if (base_face_id != DEFAULT_FACE_ID
+      || XINT (it->w->hscroll)
+      || (! WINDOW_FULL_WIDTH_P (it->w)
+         && ((!NILP (Vtruncate_partial_width_windows)
+              && !INTEGERP (Vtruncate_partial_width_windows))
+             || (INTEGERP (Vtruncate_partial_width_windows)
+                 && (WINDOW_TOTAL_COLS (it->w)
+                     < XINT (Vtruncate_partial_width_windows))))))
+    it->line_wrap = TRUNCATE;
+  else if (NILP (current_buffer->truncate_lines))
+    it->line_wrap = NILP (current_buffer->word_wrap)
+      ? WINDOW_WRAP : WORD_WRAP;
+  else
+    it->line_wrap = TRUNCATE;
 
   /* Get dimensions of truncation and continuation glyphs.  These are
      displayed as fringe bitmaps under X, so we don't need them for such
      frames.  */
   if (!FRAME_WINDOW_P (it->f))
     {
-      if (it->truncate_lines_p)
+      if (it->line_wrap == TRUNCATE)
        {
          /* We will need the truncation glyph.  */
          xassert (it->glyph_row == NULL);
@@ -2686,7 +2735,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
         for window-based redisplay.  */
       if (!FRAME_WINDOW_P (it->f))
        {
-         if (it->truncate_lines_p)
+         if (it->line_wrap == TRUNCATE)
            it->last_visible_x -= it->truncation_pixel_width;
          else
            it->last_visible_x -= it->continuation_pixel_width;
@@ -2709,11 +2758,11 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
     {
       struct face *face;
 
-      it->face_id = base_face_id;
+      it->face_id = remapped_base_face_id;
 
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
-      face = FACE_FROM_ID (it->f, base_face_id);
+      face = FACE_FROM_ID (it->f, remapped_base_face_id);
       if (face->box != FACE_NO_BOX)
        it->start_of_box_run_p = 1;
     }
@@ -2759,7 +2808,7 @@ start_display (it, w, pos)
 
   /* Don't reseat to previous visible line start if current start
      position is in a string or image.  */
-  if (it->method == GET_FROM_BUFFER && !it->truncate_lines_p)
+  if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
     {
       int start_at_line_beg_p;
       int first_y = it->current_y;
@@ -2784,7 +2833,7 @@ start_display (it, w, pos)
             taken us to the start of the continuation line but to the
             end of the continued line.  */
          if (it->current_x > 0
-             && !it->truncate_lines_p /* Lines are continued.  */
+             && it->line_wrap != TRUNCATE /* Lines are continued.  */
              && (/* And glyph doesn't fit on the line.  */
                  new_x > it->last_visible_x
                  /* Or it fits exactly and we're on a window
@@ -3056,6 +3105,7 @@ handle_stop (it)
   it->current.dpvec_index = -1;
   handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
   it->ignore_overlay_strings_at_pos_p = 0;
+  it->ellipsis_p = 0;
 
   /* Use face of preceding text for ellipsis (if invisible) */
   if (it->selective_display_ellipsis_p)
@@ -3076,10 +3126,14 @@ handle_stop (it)
            {
              /* We still want to show before and after strings from
                 overlays even if the actual buffer text is replaced.  */
-             if (!handle_overlay_change_p || it->sp > 1)
-               return;
-             if (!get_overlay_strings_1 (it, 0, 0))
-               return;
+             if (!handle_overlay_change_p
+                 || it->sp > 1
+                 || !get_overlay_strings_1 (it, 0, 0))
+               {
+                 if (it->ellipsis_p)
+                   setup_for_ellipsis (it, 0);
+                 return;
+               }
              it->ignore_overlay_strings_at_pos_p = 1;
              it->string_from_display_prop_p = 0;
              handle_overlay_change_p = 0;
@@ -3103,6 +3157,12 @@ handle_stop (it)
          if (handle_overlay_change_p)
            handled = handle_overlay_change (it);
        }
+
+      if (it->ellipsis_p)
+       {
+         setup_for_ellipsis (it, 0);
+         break;
+       }
     }
   while (handled == HANDLED_RECOMPUTE_PROPS);
 
@@ -3786,7 +3846,7 @@ handle_invisible_prop (it)
                  it->position.charpos = IT_CHARPOS (*it) - 1;
                  it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
                }
-              setup_for_ellipsis (it, 0);
+             it->ellipsis_p = 1;
              /* Let the ellipsis display before
                 considering any properties of the following char.
                 Fixes jasonr@gnu.org 01 Oct 07 bug.  */
@@ -4079,7 +4139,8 @@ handle_single_display_spec (it, spec, object, overlay, position,
              /* Value is a multiple of the canonical char height.  */
              struct face *face;
 
-             face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
+             face = FACE_FROM_ID (it->f,
+                                  lookup_basic_face (it->f, DEFAULT_FACE_ID));
              new_height = (XFLOATINT (it->font_height)
                            * XINT (face->lface[LFACE_HEIGHT_INDEX]));
            }
@@ -4189,7 +4250,7 @@ handle_single_display_spec (it, spec, object, overlay, position,
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
-      int face_id = DEFAULT_FACE_ID;
+      int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
       int fringe_bitmap;
 
       if (!FRAME_WINDOW_P (it->f))
@@ -4569,7 +4630,7 @@ handle_auto_composed_prop (it)
 {
   enum prop_handled handled = HANDLED_NORMALLY;
 
-  if (FRAME_WINDOW_P (it->f) && FUNCTIONP (Vauto_composition_function))
+  if (FUNCTIONP (Vauto_composition_function))
     {
       Lisp_Object val = Qnil;
       EMACS_INT pos, limit = -1;
@@ -4635,8 +4696,10 @@ handle_auto_composed_prop (it)
              int count = SPECPDL_INDEX ();
              Lisp_Object args[5];
 
-             limit = font_range (pos, limit, FACE_FROM_ID (it->f, it->face_id),
-                                 it->f, it->string);
+             if (FRAME_WINDOW_P (it->f))
+               limit = font_range (pos, limit,
+                                   FACE_FROM_ID (it->f, it->face_id),
+                                   it->f, it->string);
              args[0] = Vauto_composition_function;
              specbind (Qauto_composition_function, Qnil);
              args[1] = make_number (pos);
@@ -4805,8 +4868,8 @@ next_overlay_string (it)
       /* No more overlay strings.  Restore IT's settings to what
         they were before overlay strings were processed, and
         continue to deliver from current_buffer.  */
-      int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
 
+      it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0);
       pop_it (it);
       xassert (it->sp > 0
               || it->method == GET_FROM_COMPOSITION
@@ -4822,11 +4885,6 @@ next_overlay_string (it)
         next_element_from_buffer doesn't try it again.  */
       if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos)
        it->overlay_strings_at_end_processed_p = 1;
-
-      /* If we have to display `...' for invisible text, set
-        the iterator up for that.  */
-      if (display_ellipsis_p)
-       setup_for_ellipsis (it, 0);
     }
   else
     {
@@ -5189,6 +5247,7 @@ push_it (it)
   p->string_nchars = it->string_nchars;
   p->area = it->area;
   p->multibyte_p = it->multibyte_p;
+  p->avoid_cursor_p = it->avoid_cursor_p;
   p->space_width = it->space_width;
   p->font_height = it->font_height;
   p->voffset = it->voffset;
@@ -5250,6 +5309,7 @@ pop_it (it)
   it->string_nchars = p->string_nchars;
   it->area = p->area;
   it->multibyte_p = p->multibyte_p;
+  it->avoid_cursor_p = p->avoid_cursor_p;
   it->space_width = p->space_width;
   it->font_height = p->font_height;
   it->voffset = p->voffset;
@@ -5421,6 +5481,7 @@ back_to_previous_visible_line_start (it)
        pos = --IT_CHARPOS (it2);
        --IT_BYTEPOS (it2);
        it2.sp = 0;
+       it2.string_from_display_prop_p = 0;
        if (handle_display_prop (&it2) == HANDLED_RETURN
            && !NILP (val = get_char_property_and_overlay
                      (make_number (pos), Qdisplay, Qnil, &overlay))
@@ -5571,6 +5632,7 @@ reseat_1 (it, pos, set_stop_p)
   IT_STRING_CHARPOS (*it) = -1;
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
+  it->string_from_display_prop_p = 0;
   it->method = GET_FROM_BUFFER;
   it->object = it->w->buffer;
   it->area = TEXT_AREA;
@@ -6134,7 +6196,12 @@ set_iterator_to_next (it, reseat_p)
          /* IT->string is an overlay string.  Advance to the
             next, if there is one.  */
          if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
-           next_overlay_string (it);
+           {
+             it->ellipsis_p = 0;
+             next_overlay_string (it);
+             if (it->ellipsis_p)
+               setup_for_ellipsis (it, 0);
+           }
        }
       else
        {
@@ -6195,9 +6262,9 @@ next_element_from_display_vector (it)
 
   /* KFS: This code used to check ip->dpvec[0] instead of the current element.
           That seemed totally bogus - so I changed it...  */
+  gc = it->dpvec[it->current.dpvec_index];
 
-  if ((gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc))
-      && GLYPH_CODE_CHAR_VALID_P (gc))
+  if (GLYPH_CODE_P (gc) && GLYPH_CODE_CHAR_VALID_P (gc))
     {
       it->c = GLYPH_CODE_CHAR (gc);
       it->len = CHAR_BYTES (it->c);
@@ -6626,17 +6693,28 @@ next_element_from_composition (it)
      display is on.  */
 
 static enum move_it_result
-move_it_in_display_line_to (it, to_charpos, to_x, op)
-     struct it *it;
-     int to_charpos, to_x, op;
+move_it_in_display_line_to (struct it *it,
+                           EMACS_INT to_charpos, int to_x,
+                           enum move_operation_enum op)
 {
   enum move_it_result result = MOVE_UNDEFINED;
   struct glyph_row *saved_glyph_row;
+  struct it wrap_it, atpos_it, atx_it;
+  int may_wrap = 0;
 
   /* Don't produce glyphs in produce_glyphs.  */
   saved_glyph_row = it->glyph_row;
   it->glyph_row = NULL;
 
+  /* Use wrap_it to save a copy of IT wherever a word wrap could
+     occur.  Use atpos_it to save a copy of IT at the desired buffer
+     position, if found, so that we can scan ahead and check if the
+     word later overshoots the window edge.  Use atx_it similarly, for
+     pixel positions.  */
+  wrap_it.sp = -1;
+  atpos_it.sp = -1;
+  atx_it.sp = -1;
+
 #define BUFFER_POS_REACHED_P()                                 \
   ((op & MOVE_TO_POS) != 0                                     \
    && BUFFERP (it->object)                                     \
@@ -6645,46 +6723,97 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
        || (it->method == GET_FROM_DISPLAY_VECTOR               \
           && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
 
+  /* If there's a line-/wrap-prefix, handle it.  */
+  if (it->hpos == 0 && it->method == GET_FROM_BUFFER
+      && it->current_y < it->last_visible_y)
+    handle_line_prefix (it);
 
   while (1)
     {
       int x, i, ascent = 0, descent = 0;
 
-      /* Stop if we move beyond TO_CHARPOS (after an image or stretch glyph).  */
+/* Utility macro to reset an iterator with x, ascent, and descent.  */
+#define IT_RESET_X_ASCENT_DESCENT(IT)                  \
+  ((IT)->current_x = x, (IT)->max_ascent = ascent,     \
+   (IT)->max_descent = descent)
+
+      /* Stop if we move beyond TO_CHARPOS (after an image or stretch
+        glyph).  */
       if ((op & MOVE_TO_POS) != 0
          && BUFFERP (it->object)
          && it->method == GET_FROM_BUFFER
          && IT_CHARPOS (*it) > to_charpos)
        {
-         result = MOVE_POS_MATCH_OR_ZV;
-         break;
+         if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+           {
+             result = MOVE_POS_MATCH_OR_ZV;
+             break;
+           }
+         else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
+           /* If wrap_it is valid, the current position might be in a
+              word that is wrapped.  So, save the iterator in
+              atpos_it and continue to see if wrapping happens.  */
+           atpos_it = *it;
        }
 
       /* Stop when ZV reached.
          We used to stop here when TO_CHARPOS reached as well, but that is
          too soon if this glyph does not fit on this line.  So we handle it
          explicitly below.  */
-      if (!get_next_display_element (it)
-         || (it->truncate_lines_p
-             && BUFFER_POS_REACHED_P ()))
+      if (!get_next_display_element (it))
        {
          result = MOVE_POS_MATCH_OR_ZV;
          break;
        }
 
-      /* The call to produce_glyphs will get the metrics of the
-        display element IT is loaded with.  We record in x the
-        x-position before this display element in case it does not
-        fit on the line.  */
-      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)
+      if (it->line_wrap == TRUNCATE)
        {
-         ascent = it->max_ascent;
-         descent = it->max_descent;
+         if (BUFFER_POS_REACHED_P ())
+           {
+             result = MOVE_POS_MATCH_OR_ZV;
+             break;
+           }
        }
+      else
+       {
+         if (it->line_wrap == WORD_WRAP)
+           {
+             if (IT_DISPLAYING_WHITESPACE (it))
+               may_wrap = 1;
+             else if (may_wrap)
+               {
+                 /* We have reached a glyph that follows one or more
+                    whitespace characters.  If the position is
+                    already found, we are done.  */
+                 if (atpos_it.sp >= 0)
+                   {
+                     *it = atpos_it;
+                     result = MOVE_POS_MATCH_OR_ZV;
+                     goto done;
+                   }
+                 if (atx_it.sp >= 0)
+                   {
+                     *it = atx_it;
+                     result = MOVE_X_REACHED;
+                     goto done;
+                   }
+                 /* Otherwise, we can wrap here.  */
+                 wrap_it = *it;
+                 may_wrap = 0;
+               }
+           }
+       }
+
+      /* Remember the line height for the current line, in case
+        the next element doesn't fit on the line.  */
+      ascent = it->max_ascent;
+      descent = it->max_descent;
+
+      /* The call to produce_glyphs will get the metrics of the
+        display element IT is loaded with.  Record the x-position
+        before this display element, in case it doesn't fit on the
+        line.  */
+      x = it->current_x;
 
       PRODUCE_GLYPHS (it);
 
@@ -6711,7 +6840,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
         next line.
 
         Note that both for tabs and padding glyphs, all glyphs have
-        the same width.   */
+        the same width.  */
       if (it->nglyphs)
        {
          /* More than one glyph or glyph doesn't fit on line.  All
@@ -6729,19 +6858,39 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
              if ((op & MOVE_TO_X) && new_x > to_x)
                {
                  if (BUFFER_POS_REACHED_P ())
-                   goto buffer_pos_reached;
-                 it->current_x = x;
-                 result = MOVE_X_REACHED;
-                 break;
+                   {
+                     if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+                       goto buffer_pos_reached;
+                     if (atpos_it.sp < 0)
+                       {
+                         atpos_it = *it;
+                         IT_RESET_X_ASCENT_DESCENT (&atpos_it);
+                       }
+                   }
+                 else
+                   {
+                     if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+                       {
+                         it->current_x = x;
+                         result = MOVE_X_REACHED;
+                         break;
+                       }
+                     if (atx_it.sp < 0)
+                       {
+                         atx_it = *it;
+                         IT_RESET_X_ASCENT_DESCENT (&atx_it);
+                       }
+                   }
                }
-             else if (/* Lines are continued.  */
-                      !it->truncate_lines_p
-                      && (/* And glyph doesn't fit on the line.  */
-                          new_x > it->last_visible_x
-                          /* Or it fits exactly and we're on a window
-                             system frame.  */
-                          || (new_x == it->last_visible_x
-                              && FRAME_WINDOW_P (it->f))))
+
+             if (/* Lines are continued.  */
+                 it->line_wrap != TRUNCATE
+                 && (/* And glyph doesn't fit on the line.  */
+                     new_x > it->last_visible_x
+                     /* Or it fits exactly and we're on a window
+                        system frame.  */
+                     || (new_x == it->last_visible_x
+                         && FRAME_WINDOW_P (it->f))))
                {
                  if (/* IT->hpos == 0 means the very first glyph
                         doesn't fit on the line, e.g. a wide image.  */
@@ -6761,10 +6910,21 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                             now that we know it fits in this row.  */
                          if (BUFFER_POS_REACHED_P ())
                            {
-                             it->hpos = hpos_before_this_char;
-                             it->current_x = x_before_this_char;
-                             result = MOVE_POS_MATCH_OR_ZV;
-                             break;
+                             if (it->line_wrap != WORD_WRAP
+                                 || wrap_it.sp < 0)
+                               {
+                                 it->hpos = hpos_before_this_char;
+                                 it->current_x = x_before_this_char;
+                                 result = MOVE_POS_MATCH_OR_ZV;
+                                 break;
+                               }
+                             if (it->line_wrap == WORD_WRAP
+                                 && atpos_it.sp < 0)
+                               {
+                                 atpos_it = *it;
+                                 atpos_it.current_x = x_before_this_char;
+                                 atpos_it.hpos = hpos_before_this_char;
+                               }
                            }
 
                          set_iterator_to_next (it, 1);
@@ -6794,10 +6954,13 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                        }
                    }
                  else
+                   IT_RESET_X_ASCENT_DESCENT (it);
+
+                 if (wrap_it.sp >= 0)
                    {
-                     it->current_x = x;
-                     it->max_ascent = ascent;
-                     it->max_descent = descent;
+                     *it = wrap_it;
+                     atpos_it.sp = -1;
+                     atx_it.sp = -1;
                    }
 
                  TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
@@ -6805,19 +6968,24 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                  result = MOVE_LINE_CONTINUED;
                  break;
                }
-             else if (BUFFER_POS_REACHED_P ())
-               goto buffer_pos_reached;
-             else if (new_x > it->first_visible_x)
+
+             if (BUFFER_POS_REACHED_P ())
+               {
+                 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+                   goto buffer_pos_reached;
+                 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
+                   {
+                     atpos_it = *it;
+                     IT_RESET_X_ASCENT_DESCENT (&atpos_it);
+                   }
+               }
+
+             if (new_x > it->first_visible_x)
                {
                  /* Glyph is visible.  Increment number of glyphs that
                     would be displayed.  */
                  ++it->hpos;
                }
-             else
-               {
-                 /* Glyph is completely off the left margin of the display
-                    area.  Nothing to do.  */
-               }
            }
 
          if (result != MOVE_UNDEFINED)
@@ -6826,9 +6994,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
       else if (BUFFER_POS_REACHED_P ())
        {
        buffer_pos_reached:
-         it->current_x = x;
-         it->max_ascent = ascent;
-         it->max_descent = descent;
+         IT_RESET_X_ASCENT_DESCENT (it);
          result = MOVE_POS_MATCH_OR_ZV;
          break;
        }
@@ -6856,7 +7022,7 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
 
       /* Stop if lines are truncated and IT's current x-position is
         past the right edge of the window now.  */
-      if (it->truncate_lines_p
+      if (it->line_wrap == TRUNCATE
          && it->current_x >= it->last_visible_x)
        {
 #ifdef HAVE_WINDOW_SYSTEM
@@ -6878,16 +7044,53 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
          result = MOVE_LINE_TRUNCATED;
          break;
        }
+#undef IT_RESET_X_ASCENT_DESCENT
     }
 
 #undef BUFFER_POS_REACHED_P
 
+  /* If we scanned beyond to_pos and didn't find a point to wrap at,
+     restore the saved iterator.  */
+  if (atpos_it.sp >= 0)
+    *it = atpos_it;
+  else if (atx_it.sp >= 0)
+    *it = atx_it;
+
+ done:
+
   /* Restore the iterator settings altered at the beginning of this
      function.  */
   it->glyph_row = saved_glyph_row;
   return result;
 }
 
+/* For external use.  */
+void
+move_it_in_display_line (struct it *it,
+                        EMACS_INT to_charpos, int to_x,
+                        enum move_operation_enum op)
+{
+  if (it->line_wrap == WORD_WRAP
+      && (op & MOVE_TO_X))
+    {
+      struct it save_it = *it;
+      int skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
+      /* When word-wrap is on, TO_X may lie past the end
+        of a wrapped line.  Then it->current is the
+        character on the next line, so backtrack to the
+        space before the wrap point.  */
+      if (skip == MOVE_LINE_CONTINUED)
+       {
+         int prev_x = max (it->current_x - 1, 0);
+         *it = save_it;
+         move_it_in_display_line_to
+           (it, -1, prev_x, MOVE_TO_X);
+       }
+    }
+  else
+    move_it_in_display_line_to (it, to_charpos, to_x, op);
+}
+
 
 /* Move IT forward until it satisfies one or more of the criteria in
    TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.
@@ -6960,6 +7163,9 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
        {
          struct it it_backup;
 
+         if (it->line_wrap == WORD_WRAP)
+           it_backup = *it;
+
          /* TO_Y specified means stop at TO_X in the line containing
             TO_Y---or at TO_CHARPOS if this is reached first.  The
             problem is that we can't really tell whether the line
@@ -6972,28 +7178,19 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
             If we didn't use TO_X == 0, we would stop at the end of
             the line which is probably not what a caller would expect
             to happen.  */
-         skip = move_it_in_display_line_to (it, to_charpos,
-                                            ((op & MOVE_TO_X)
-                                             ? to_x : 0),
-                                            (MOVE_TO_X
-                                             | (op & MOVE_TO_POS)));
+         skip = move_it_in_display_line_to
+           (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
+            (MOVE_TO_X | (op & MOVE_TO_POS)));
 
          /* If TO_CHARPOS is reached or ZV, we don't have to do more.  */
          if (skip == MOVE_POS_MATCH_OR_ZV)
+           reached = 5;
+         else if (skip == MOVE_X_REACHED)
            {
-             reached = 5;
-             break;
-           }
-
-         /* If TO_X was reached, we would like to know whether TO_Y
-            is in the line.  This can only be said if we know the
-            total line height which requires us to scan the rest of
-            the line.  */
-         if (skip == MOVE_X_REACHED)
-           {
-             /* Wait!  We can conclude that TO_Y is in the line if
-                the already scanned glyphs make the line tall enough
-                because further scanning doesn't make it shorter.  */
+             /* If TO_X was reached, we want to know whether TO_Y is
+                in the line.  We know this is the case if the already
+                scanned glyphs make the line tall enough.  Otherwise,
+                we must check by scanning the rest of the line.  */
              line_height = it->max_ascent + it->max_descent;
              if (to_y >= it->current_y
                  && to_y < it->current_y + line_height)
@@ -7006,27 +7203,48 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
              skip2 = move_it_in_display_line_to (it, to_charpos, -1,
                                                  op & MOVE_TO_POS);
              TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
-           }
-
-         /* Now, decide whether TO_Y is in this line.  */
-         line_height = it->max_ascent + it->max_descent;
-         TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
+             line_height = it->max_ascent + it->max_descent;
+             TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
 
-         if (to_y >= it->current_y
-             && to_y < it->current_y + line_height)
-           {
-             if (skip == MOVE_X_REACHED)
-               /* If TO_Y is in this line and TO_X was reached above,
-                  we scanned too far.  We have to restore IT's settings
-                  to the ones before skipping.  */
-               *it = it_backup;
-             reached = 6;
+             if (to_y >= it->current_y
+                 && to_y < it->current_y + line_height)
+               {
+                 /* If TO_Y is in this line and TO_X was reached
+                    above, we scanned too far.  We have to restore
+                    IT's settings to the ones before skipping.  */
+                 *it = it_backup;
+                 reached = 6;
+               }
+             else
+               {
+                 skip = skip2;
+                 if (skip == MOVE_POS_MATCH_OR_ZV)
+                   reached = 7;
+               }
            }
-         else if (skip == MOVE_X_REACHED)
+         else
            {
-             skip = skip2;
-             if (skip == MOVE_POS_MATCH_OR_ZV)
-               reached = 7;
+             /* Check whether TO_Y is in this line.  */
+             line_height = it->max_ascent + it->max_descent;
+             TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
+
+             if (to_y >= it->current_y
+                 && to_y < it->current_y + line_height)
+               {
+                 /* When word-wrap is on, TO_X may lie past the end
+                    of a wrapped line.  Then it->current is the
+                    character on the next line, so backtrack to the
+                    space before the wrap point.  */
+                 if (skip == MOVE_LINE_CONTINUED
+                     && it->line_wrap == WORD_WRAP)
+                   {
+                     int prev_x = max (it->current_x - 1, 0);
+                     *it = it_backup;
+                     skip = move_it_in_display_line_to
+                       (it, -1, prev_x, MOVE_TO_X);
+                   }
+                 reached = 6;
+               }
            }
 
          if (reached)
@@ -7086,6 +7304,30 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
 
  out:
 
+  /* On text terminals, we may stop at the end of a line in the middle
+     of a multi-character glyph.  If the glyph itself is continued,
+     i.e. it is actually displayed on the next line, don't treat this
+     stopping point as valid; move to the next line instead (unless
+     that brings us offscreen).  */
+  if (!FRAME_WINDOW_P (it->f)
+      && op & MOVE_TO_POS
+      && IT_CHARPOS (*it) == to_charpos
+      && it->what == IT_CHARACTER
+      && it->nglyphs > 1
+      && it->line_wrap == WINDOW_WRAP
+      && it->current_x == it->last_visible_x - 1
+      && it->c != '\n'
+      && it->c != '\t'
+      && it->vpos < XFASTINT (it->w->window_end_vpos))
+    {
+      it->continuation_lines_width += it->current_x;
+      it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
+      it->current_y += it->max_ascent + it->max_descent;
+      ++it->vpos;
+      last_height = it->max_ascent + it->max_descent;
+      last_max_ascent = it->max_ascent;
+    }
+
   TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
 }
 
@@ -7268,41 +7510,6 @@ move_it_past_eol (it)
 }
 
 
-#if 0 /* Currently not used.  */
-
-/* Return non-zero if some text between buffer positions START_CHARPOS
-   and END_CHARPOS is invisible.  IT->window is the window for text
-   property lookup.  */
-
-static int
-invisible_text_between_p (it, start_charpos, end_charpos)
-     struct it *it;
-     int start_charpos, end_charpos;
-{
-  Lisp_Object prop, limit;
-  int invisible_found_p;
-
-  xassert (it != NULL && start_charpos <= end_charpos);
-
-  /* Is text at START invisible?  */
-  prop = Fget_char_property (make_number (start_charpos), Qinvisible,
-                            it->window);
-  if (TEXT_PROP_MEANS_INVISIBLE (prop))
-    invisible_found_p = 1;
-  else
-    {
-      limit = Fnext_single_char_property_change (make_number (start_charpos),
-                                                Qinvisible, Qnil,
-                                                make_number (end_charpos));
-      invisible_found_p = XFASTINT (limit) < end_charpos;
-    }
-
-  return invisible_found_p;
-}
-
-#endif /* 0 */
-
-
 /* Move IT by a specified number DVPOS of screen lines down.  DVPOS
    negative means move up.  DVPOS == 0 means move to the start of the
    screen line.  NEED_Y_P non-zero means calculate IT->current_y.  If
@@ -8086,6 +8293,9 @@ ensure_echo_area_buffers ()
        sprintf (name, " *Echo Area %d*", i);
        echo_buffer[i] = Fget_buffer_create (build_string (name));
        XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
+       /* to force word wrap in echo area - 
+          it was decided to postpone this*/
+       /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
 
        for (j = 0; j < 2; ++j)
          if (EQ (old_buffer, echo_area_buffer[j]))
@@ -8535,7 +8745,7 @@ resize_mini_window (w, exact_p)
       max_height = min (total_height, max_height);
 
       /* Find out the height of the text in the window.  */
-      if (it.truncate_lines_p)
+      if (it.line_wrap == TRUNCATE)
        height = 1;
       else
        {
@@ -9271,7 +9481,32 @@ x_consider_frame_title (frame)
       if (! STRINGP (f->name)
          || SBYTES (f->name) != len
          || bcmp (title, SDATA (f->name), len) != 0)
-       x_implicitly_set_name (f, make_string (title, len), Qnil);
+        {
+#ifdef HAVE_NS
+          if (FRAME_NS_P (f))
+            {
+              if (!MINI_WINDOW_P(XWINDOW(f->selected_window)))
+                {
+                  if (EQ (fmt, Qt))
+                    ns_set_name_as_filename (f);
+                  else
+                    x_implicitly_set_name (f, make_string(title, len),
+                                           Qnil);
+                }
+            }
+          else
+#endif
+           x_implicitly_set_name (f, make_string (title, len), Qnil);
+        }
+#ifdef HAVE_NS
+      if (FRAME_NS_P (f))
+        {
+          /* do this also for frames with explicit names */
+          ns_implicitly_set_icon_type(f);
+          ns_set_doc_edited(f, Fbuffer_modified_p
+                            (XWINDOW (f->selected_window)->buffer), Qnil);
+        }
+#endif
     }
 }
 
@@ -9366,9 +9601,6 @@ prepare_menu_bars ()
          menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
-#ifdef MAC_OS
-         mac_update_title_bar (f, 0);
-#endif
 #endif
          UNGCPRO;
        }
@@ -9381,9 +9613,6 @@ prepare_menu_bars ()
       update_menu_bar (sf, 1, 0);
 #ifdef HAVE_WINDOW_SYSTEM
       update_tool_bar (sf, 1);
-#ifdef MAC_OS
-      mac_update_title_bar (sf, 1);
-#endif
 #endif
     }
 
@@ -9424,19 +9653,10 @@ update_menu_bar (f, save_match_data, hooks_run)
   window = FRAME_SELECTED_WINDOW (f);
   w = XWINDOW (window);
 
-#if 0 /* The if statement below this if statement used to include the
-         condition !NILP (w->update_mode_line), rather than using
-         update_mode_lines directly, and this if statement may have
-         been added to make that condition work.  Now the if
-         statement below matches its comment, this isn't needed.  */
-  if (update_mode_lines)
-    w->update_mode_line = Qt;
-#endif
-
   if (FRAME_WINDOW_P (f)
       ?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
       FRAME_EXTERNAL_MENU_BAR (f)
 #else
       FRAME_MENU_BAR_LINES (f) > 0
@@ -9494,11 +9714,11 @@ update_menu_bar (f, save_match_data, hooks_run)
          FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
 
          /* Redisplay the menu bar in case we changed it.  */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
          if (FRAME_WINDOW_P (f))
-           {
-#ifdef MAC_OS
+            {
+#if defined (HAVE_NS)
               /* All frames on Mac OS share the same menubar.  So only
                  the selected frame should be allowed to set it.  */
               if (f == SELECTED_FRAME ())
@@ -9509,11 +9729,11 @@ update_menu_bar (f, save_match_data, hooks_run)
            /* On a terminal screen, the menu bar is an ordinary screen
               line, and this makes it get updated.  */
            w->update_mode_line = Qt;
-#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
+#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
          /* In the non-toolkit version, the menu bar is an ordinary screen
             line, and this makes it get updated.  */
          w->update_mode_line = Qt;
-#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
+#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
 
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
@@ -9624,7 +9844,7 @@ update_tool_bar (f, save_match_data)
      struct frame *f;
      int save_match_data;
 {
-#if defined (USE_GTK) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
   int do_update = WINDOWP (f->tool_bar_window)
@@ -9932,7 +10152,7 @@ display_tool_bar_line (it, height)
              row->used[TEXT_AREA] = n_glyphs_before;
              *it = it_before;
              /* If this is the only glyph on this line, it will never fit on the
-                toolbar, so skip it.   But ensure there is at least one glyph,
+                toolbar, so skip it.  But ensure there is at least one glyph,
                 so we don't accidentally disable the tool-bar.  */
              if (n_glyphs_before == 0
                  && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
@@ -10090,7 +10310,7 @@ redisplay_tool_bar (f)
   struct it it;
   struct glyph_row *row;
 
-#if defined (USE_GTK) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
   if (FRAME_EXTERNAL_TOOL_BAR (f))
     update_frame_tool_bar (f);
   return 0;
@@ -11033,8 +11253,9 @@ static void
 select_frame_for_redisplay (frame)
      Lisp_Object frame;
 {
-  Lisp_Object tail, sym, val;
+  Lisp_Object tail, symbol, val;
   Lisp_Object old = selected_frame;
+  struct Lisp_Symbol *sym;
 
   xassert (FRAMEP (frame) && FRAME_LIVE_P (XFRAME (frame)));
 
@@ -11044,15 +11265,15 @@ select_frame_for_redisplay (frame)
     {
       for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
        if (CONSP (XCAR (tail))
-           && (sym = XCAR (XCAR (tail)),
-               SYMBOLP (sym))
-           && (sym = indirect_variable (sym),
-               val = SYMBOL_VALUE (sym),
+           && (symbol = XCAR (XCAR (tail)),
+               SYMBOLP (symbol))
+           && (sym = indirect_variable (XSYMBOL (symbol)),
+               val = sym->value,
                (BUFFER_LOCAL_VALUEP (val)))
            && XBUFFER_LOCAL_VALUE (val)->check_frame)
          /* Use find_symbol_value rather than Fsymbol_value
             to avoid an error if it is void.  */
-         find_symbol_value (sym);
+         find_symbol_value (symbol);
     } while (!EQ (frame, old) && (frame = old, 1));
 }
 
@@ -11119,7 +11340,7 @@ redisplay_internal (preserve_echo_area)
        return;
     }
 
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
   if (popup_activated ())
     return;
 #endif
@@ -11183,7 +11404,7 @@ redisplay_internal (preserve_echo_area)
         the whole thing.  */
       windows_or_buffers_changed++;
       SET_FRAME_GARBAGED (sf);
-#ifndef WINDOWSNT
+#ifndef DOS_NT
       set_tty_color_mode (FRAME_TTY (sf), sf);
 #endif
       FRAME_TTY (sf)->previous_frame = sf;
@@ -11309,6 +11530,10 @@ redisplay_internal (preserve_echo_area)
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = 1;
+/* FIXME: this causes all frames to be updated, which seems unnecessary
+   since only the current frame needs to be considered.  This function needs
+   to be rewritten with two variables, consider_all_windows and
+   consider_all_frames. */
       consider_all_windows_p = 1;
       ++windows_or_buffers_changed;
       ++update_mode_lines;
@@ -11618,11 +11843,6 @@ redisplay_internal (preserve_echo_area)
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
                  pause |= update_frame (f, 0, 0);
-#if 0  /* Exiting the loop can leave the wrong value for buffer_shared.  */
-                 if (pause)
-                   break;
-#endif
-
                  f->updated_p = 1;
                }
            }
@@ -11916,11 +12136,6 @@ mark_window_display_accurate_1 (w, accurate_p)
   if (accurate_p)
     {
       w->window_end_valid = w->buffer;
-#if 0 /* This is incorrect with variable-height lines.  */
-      xassert (XINT (w->window_end_vpos)
-              < (WINDOW_TOTAL_LINES (w)
-                 - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
-#endif
       w->update_mode_line = Qnil;
     }
 }
@@ -12110,7 +12325,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
   while (glyph < end
         && !INTEGERP (glyph->object)
         && (!BUFFERP (glyph->object)
-            || (last_pos = glyph->charpos) < pt_old))
+            || (last_pos = glyph->charpos) < pt_old
+            || glyph->avoid_cursor_p))
     {
       if (! STRINGP (glyph->object))
        {
@@ -12420,19 +12636,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  struct text_pos scroll_margin_pos;
-  struct text_pos pos;
-  struct text_pos startp;
+  struct text_pos pos, startp;
   struct it it;
-  Lisp_Object window_end;
-  int this_scroll_margin;
-  int dy = 0;
-  int scroll_max;
-  int rc;
-  int amount_to_scroll = 0;
-  Lisp_Object aggressive;
-  int height;
+  int this_scroll_margin, scroll_max, rc, height;
+  int dy = 0, amount_to_scroll = 0, scroll_down_p = 0;
   int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
+  Lisp_Object aggressive;
+  int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f);
 
 #if GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
@@ -12450,69 +12660,67 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   else
     this_scroll_margin = 0;
 
-  /* Force scroll_conservatively to have a reasonable value so it doesn't
-     cause an overflow while computing how much to scroll.  */
-  if (scroll_conservatively)
-    scroll_conservatively = min (scroll_conservatively,
-                                 MOST_POSITIVE_FIXNUM / FRAME_LINE_HEIGHT (f));
-
-  /* Compute how much we should try to scroll maximally to bring point
-     into view.  */
-  if (scroll_step || scroll_conservatively || temp_scroll_step)
-    scroll_max = max (scroll_step,
-                     max (scroll_conservatively, temp_scroll_step));
+  /* Force scroll_conservatively to have a reasonable value, to avoid
+     overflow while computing how much to scroll.  Note that it's
+     fairly common for users to supply scroll-conservatively equal to
+     `most-positive-fixnum', which can be larger than INT_MAX.  */
+  if (scroll_conservatively > scroll_limit)
+    {
+      scroll_conservatively = scroll_limit;
+      scroll_max = INT_MAX;
+    }
+  else if (scroll_step || scroll_conservatively || temp_scroll_step)
+    /* Compute how much we should try to scroll maximally to bring
+       point into view.  */
+    scroll_max = (max (scroll_step,
+                      max (scroll_conservatively, temp_scroll_step))
+                 * FRAME_LINE_HEIGHT (f));
   else if (NUMBERP (current_buffer->scroll_down_aggressively)
           || NUMBERP (current_buffer->scroll_up_aggressively))
-    /* We're trying to scroll because of aggressive scrolling
-       but no scroll_step is set.  Choose an arbitrary one.  Maybe
-       there should be a variable for this.  */
-    scroll_max = 10;
+    /* We're trying to scroll because of aggressive scrolling but no
+       scroll_step is set.  Choose an arbitrary one.  */
+    scroll_max = 10 * FRAME_LINE_HEIGHT (f);
   else
     scroll_max = 0;
-  scroll_max *= FRAME_LINE_HEIGHT (f);
-
-  /* Decide whether we have to scroll down.  Start at the window end
-     and move this_scroll_margin up to find the position of the scroll
-     margin.  */
-  window_end = Fwindow_end (window, Qt);
 
  too_near_end:
 
-  CHARPOS (scroll_margin_pos) = XINT (window_end);
-  BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
-
-  if (this_scroll_margin || extra_scroll_margin_lines)
+  /* Decide whether we have to scroll down.  */
+  if (PT > CHARPOS (startp))
     {
-      start_display (&it, w, scroll_margin_pos);
-      if (this_scroll_margin)
-       move_it_vertically_backward (&it, this_scroll_margin);
-      if (extra_scroll_margin_lines)
-       move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
-      scroll_margin_pos = it.current.pos;
-    }
+      int scroll_margin_y;
 
-  if (PT >= CHARPOS (scroll_margin_pos))
-    {
-      int y0;
+      /* Compute the pixel ypos of the scroll margin, then move it to
+        either that ypos or PT, whichever comes first.  */
+      start_display (&it, w, startp);
+      scroll_margin_y = it.last_visible_y - this_scroll_margin
+       - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines;
+      move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
+                 (MOVE_TO_POS | MOVE_TO_Y));
 
-      /* Point is in the scroll margin at the bottom of the window, or
-        below.  Compute a new window start that makes point visible.  */
+      if (PT > CHARPOS (it.current.pos))
+       {
+         /* Point is in the scroll margin at the bottom of the
+            window, or below.  Compute the distance from the scroll
+            margin to PT, and give up if the distance is greater than
+            scroll_max.  */
+         move_it_to (&it, PT, -1, it.last_visible_y - 1, -1,
+                     MOVE_TO_POS | MOVE_TO_Y);
 
-      /* Compute the distance from the scroll margin to PT.
-        Give up if the distance is greater than scroll_max.  */
-      start_display (&it, w, scroll_margin_pos);
-      y0 = it.current_y;
-      move_it_to (&it, PT, 0, it.last_visible_y, -1,
-                 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+         /* To make point visible, we must move the window start down
+            so that the cursor line is visible, which means we have
+            to add in the height of the cursor line.  */
+         dy = line_bottom_y (&it) - scroll_margin_y;
 
-      /* To make point visible, we have to move the window start
-        down so that the line the cursor is in is visible, which
-        means we have to add in the height of the cursor line.  */
-      dy = line_bottom_y (&it) - y0;
+         if (dy > scroll_max)
+           return SCROLLING_FAILED;
 
-      if (dy > scroll_max)
-       return SCROLLING_FAILED;
+         scroll_down_p = 1;
+       }
+    }
 
+  if (scroll_down_p)
+    {
       /* Move the window start down.  If scrolling conservatively,
         move it just enough down to make point visible.  If
         scroll_step is set, move it down by scroll_step.  */
@@ -12552,9 +12760,10 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     }
   else
     {
+      struct text_pos scroll_margin_pos = startp;
+
       /* See if point is inside the scroll margin at the top of the
          window.  */
-      scroll_margin_pos = startp;
       if (this_scroll_margin)
        {
          start_display (&it, w, startp);
@@ -12803,9 +13012,13 @@ try_cursor_movement (window, startp, scroll_step)
 
       /* Scroll if point within this distance from the top or bottom
         of the window.  This is a pixel value.  */
-      this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+      if (scroll_margin > 0)
+       {
+         this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+         this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+       }
+      else
+       this_scroll_margin = 0;
 
       top_scroll_margin = this_scroll_margin;
       if (WINDOW_WANTS_HEADER_LINE_P (w))
@@ -13249,7 +13462,6 @@ redisplay_window (window, just_this_one_p)
     {
       /* We set this later on if we have to adjust point.  */
       int new_vpos = -1;
-      int val;
 
       w->force_start = Qnil;
       w->vscroll = 0;
@@ -13283,16 +13495,15 @@ redisplay_window (window, just_this_one_p)
 
       /* Redisplay, then check if cursor has been set during the
         redisplay.  Give up if new fonts were loaded.  */
-      val = try_window (window, startp, 1);
-      if (!val)
+      /* We used to issue a CHECK_MARGINS argument to try_window here,
+        but this causes scrolling to fail when point begins inside
+        the scroll margin (bug#148) -- cyd  */
+      if (!try_window (window, startp, 0))
        {
          w->force_start = Qt;
          clear_glyph_matrix (w->desired_matrix);
          goto need_larger_matrices;
        }
-      /* Point was outside the scroll margins.  */
-      if (val < 0)
-       new_vpos = window_box_height (w) / 2;
 
       if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
        {
@@ -13423,11 +13634,16 @@ redisplay_window (window, just_this_one_p)
          && NILP (do_mouse_tracking)
          && CHARPOS (startp) > BEGV
          && CHARPOS (startp) > BEG + beg_unchanged
-         && CHARPOS (startp) <= Z - end_unchanged)
+         && CHARPOS (startp) <= Z - end_unchanged
+         /* Even if w->start_at_line_beg is nil, a new window may
+            start at a line_beg, since that's how set_buffer_window
+            sets it.  So, we need to check the return value of
+            compute_window_start_on_continuation_line.  (See also
+            bug#197).  */
+         && XMARKER (w->start)->buffer == current_buffer
+         && compute_window_start_on_continuation_line (w))
        {
          w->force_start = Qt;
-         if (XMARKER (w->start)->buffer == current_buffer)
-           compute_window_start_on_continuation_line (w);
          SET_TEXT_POS_FROM_MARKER (startp, w->start);
          goto force_start;
        }
@@ -13554,11 +13770,6 @@ redisplay_window (window, just_this_one_p)
     {
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
       move_it_vertically_backward (&it, 0);
-#if 0
-      /* I think this assert is bogus if buffer contains
-        invisible text or images.  KFS.  */
-      xassert (IT_CHARPOS (it) <= PT);
-#endif
       it.current_y = 0;
     }
 
@@ -13719,8 +13930,8 @@ redisplay_window (window, just_this_one_p)
 
       if (FRAME_WINDOW_P (f))
        {
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
          redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
 #else
          redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
@@ -13735,7 +13946,7 @@ redisplay_window (window, just_this_one_p)
 #ifdef HAVE_WINDOW_SYSTEM
       if (FRAME_WINDOW_P (f))
         {
-#if defined (USE_GTK) || USE_MAC_TOOLBAR
+#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
           redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
           redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
@@ -13842,9 +14053,13 @@ try_window (window, pos, check_margins)
     {
       int this_scroll_margin;
 
-      this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+      if (scroll_margin > 0)
+       {
+         this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+         this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+       }
+      else
+       this_scroll_margin = 0;
 
       if ((w->cursor.y >= 0    /* not vscrolled */
           && w->cursor.y < this_scroll_margin
@@ -13854,7 +14069,7 @@ try_window (window, pos, check_margins)
             seems to give wrong results.  We don't want to recenter
             when the last line is partly visible, we want to allow
             that case to be handled in the usual way.  */
-         || (w->cursor.y + 1) > it.last_visible_y)
+         || w->cursor.y > it.last_visible_y - this_scroll_margin - 1)
        {
          w->cursor.vpos = -1;
          clear_glyph_matrix (w->desired_matrix);
@@ -14375,9 +14590,10 @@ find_last_unchanged_at_beg_row (w)
   int yb = window_text_bottom_y (w);
 
   /* Find the last row displaying unchanged text.  */
-  row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
-        && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
+  for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+       MATRIX_ROW_DISPLAYS_TEXT_P (row)
+        && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
+       ++row)
     {
       if (/* If row ends before first_changed_pos, it is unchanged,
             except in some case.  */
@@ -14394,10 +14610,8 @@ find_last_unchanged_at_beg_row (w)
        row_found = row;
 
       /* Stop if last visible row.  */
-     if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
+      if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
        break;
-
-      ++row;
     }
 
   return row_found;
@@ -14713,6 +14927,12 @@ try_window_id (w)
   if (overlay_arrows_changed_p ())
     GIVE_UP (12);
 
+  /* When word-wrap is on, adding a space to the first word of a
+     wrapped line can change the wrap position, altering the line
+     above it.  It might be worthwhile to handle this more
+     intelligently, but for now just redisplay from scratch.  */
+  if (!NILP (XBUFFER (w->buffer)->word_wrap))
+    GIVE_UP (21);
 
   /* Make sure beg_unchanged and end_unchanged are up to date.  Do it
      only if buffer has really changed.  The reason is that the gap is
@@ -16178,6 +16398,97 @@ cursor_row_p (w, row)
   return cursor_row_p;
 }
 
+\f
+
+/* Push the display property PROP so that it will be rendered at the
+   current position in IT.  */
+
+static void
+push_display_prop (struct it *it, Lisp_Object prop)
+{
+  push_it (it);
+
+  /* Never display a cursor on the prefix.  */
+  it->avoid_cursor_p = 1;
+
+  if (STRINGP (prop))
+    {
+      if (SCHARS (prop) == 0)
+       {
+         pop_it (it);
+         return;
+       }
+
+      it->string = prop;
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
+      it->current.overlay_string_index = -1;
+      IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+      it->end_charpos = it->string_nchars = SCHARS (it->string);
+      it->method = GET_FROM_STRING;
+      it->stop_charpos = 0;
+    }
+  else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
+    {
+      it->method = GET_FROM_STRETCH;
+      it->object = prop;
+    }
+#ifdef HAVE_WINDOW_SYSTEM
+  else if (IMAGEP (prop))
+    {
+      it->what = IT_IMAGE;
+      it->image_id = lookup_image (it->f, prop);
+      it->method = GET_FROM_IMAGE;
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+  else
+    {
+      pop_it (it);             /* bogus display property, give up */
+      return;
+    }
+}
+
+/* Return the character-property PROP at the current position in IT.  */
+
+static Lisp_Object
+get_it_property (it, prop)
+     struct it *it;
+     Lisp_Object prop;
+{
+  Lisp_Object position;
+
+  if (STRINGP (it->object))
+    position = make_number (IT_STRING_CHARPOS (*it));
+  else if (BUFFERP (it->object))
+    position = make_number (IT_CHARPOS (*it));
+  else
+    return Qnil;
+
+  return Fget_char_property (position, prop, it->object);
+}
+
+/* See if there's a line- or wrap-prefix, and if so, push it on IT.  */
+
+static void
+handle_line_prefix (struct it *it)
+{
+  Lisp_Object prefix;
+  if (it->continuation_lines_width > 0)
+    {
+      prefix = get_it_property (it, Qwrap_prefix);
+      if (NILP (prefix))
+       prefix = Vwrap_prefix;
+    }
+  else
+    {
+      prefix = get_it_property (it, Qline_prefix);
+      if (NILP (prefix))
+       prefix = Vline_prefix;
+    }
+  if (! NILP (prefix))
+    push_display_prop (it, prefix);
+}
+
+\f
 
 /* Construct the glyph row IT->glyph_row in the desired matrix of
    IT->w from text at the current position of IT.  See dispextern.h
@@ -16191,6 +16502,11 @@ display_line (it)
 {
   struct glyph_row *row = it->glyph_row;
   Lisp_Object overlay_arrow_string;
+  struct it wrap_it;
+  int may_wrap = 0, wrap_x;
+  int wrap_row_used = -1, wrap_row_ascent, wrap_row_height;
+  int wrap_row_phys_ascent, wrap_row_phys_height;
+  int wrap_row_extra_line_spacing;
 
   /* We always start displaying at hpos zero even if hscrolled.  */
   xassert (it->hpos == 0 && it->current_x == 0);
@@ -16231,6 +16547,13 @@ display_line (it)
       move_it_in_display_line_to (it, ZV, it->first_visible_x,
                                  MOVE_TO_POS | MOVE_TO_X);
     }
+  else
+    {
+      /* We only do this when not calling `move_it_in_display_line_to'
+        above, because move_it_in_display_line_to calls
+        handle_line_prefix itself.  */
+      handle_line_prefix (it);
+    }
 
   /* Get the initial row height.  This is either the height of the
      text hscrolled, if there is any, or zero.  */
@@ -16285,12 +16608,30 @@ display_line (it)
 
       /* Remember the line height so far in case the next element doesn't
         fit on the line.  */
-      if (!it->truncate_lines_p)
+      if (it->line_wrap != TRUNCATE)
        {
          ascent = it->max_ascent;
          descent = it->max_descent;
          phys_ascent = it->max_phys_ascent;
          phys_descent = it->max_phys_descent;
+
+         if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
+           {
+             if (IT_DISPLAYING_WHITESPACE (it))
+               may_wrap = 1;
+             else if (may_wrap)
+               {
+                 wrap_it = *it;
+                 wrap_x = x;
+                 wrap_row_used = row->used[TEXT_AREA];
+                 wrap_row_ascent = row->ascent;
+                 wrap_row_height = row->height;
+                 wrap_row_phys_ascent = row->phys_ascent;
+                 wrap_row_phys_height = row->phys_height;
+                 wrap_row_extra_line_spacing = row->extra_line_spacing;
+                 may_wrap = 0;
+               }
+           }
        }
 
       PRODUCE_GLYPHS (it);
@@ -16350,7 +16691,7 @@ display_line (it)
              new_x = x + glyph->pixel_width;
 
              if (/* Lines are continued.  */
-                 !it->truncate_lines_p
+                 it->line_wrap != TRUNCATE
                  && (/* Glyph doesn't fit on the line.  */
                      new_x > it->last_visible_x
                      /* Or it fits exactly on a window system frame.  */
@@ -16373,6 +16714,18 @@ display_line (it)
                      ++it->hpos;
                      if (i == nglyphs - 1)
                        {
+                         /* If line-wrap is on, check if a previous
+                            wrap point was found.  */
+                         if (wrap_row_used > 0
+                             /* Even if there is a previous wrap
+                                point, continue the line here as
+                                usual, if (i) the previous character
+                                was a space or tab AND (ii) the
+                                current character is not.  */
+                             && (!may_wrap
+                                 || IT_DISPLAYING_WHITESPACE (it)))
+                           goto back_to_wrap;
+
                          set_iterator_to_next (it, 1);
 #ifdef HAVE_WINDOW_SYSTEM
                          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
@@ -16418,6 +16771,26 @@ display_line (it)
                      it->max_phys_ascent = phys_ascent;
                      it->max_phys_descent = phys_descent;
                    }
+                 else if (wrap_row_used > 0)
+                   {
+                   back_to_wrap:
+                     *it = wrap_it;
+                     it->continuation_lines_width += wrap_x;
+                     row->used[TEXT_AREA] = wrap_row_used;
+                     row->ascent = wrap_row_ascent;
+                     row->height = wrap_row_height;
+                     row->phys_ascent = wrap_row_phys_ascent;
+                     row->phys_height = wrap_row_phys_height;
+                     row->extra_line_spacing = wrap_row_extra_line_spacing;
+                     row->continued_p = 1;
+                     row->ends_at_zv_p = 0;
+                     row->exact_window_width_line_p = 0;
+                     it->continuation_lines_width += x;
+
+                     /* Make sure that a non-default face is extended
+                        up to the right margin of the window.  */
+                     extend_face_to_end_of_line (it);
+                   }
                  else if (it->c == '\t' && FRAME_WINDOW_P (it->f))
                    {
                      /* A TAB that extends past the right edge of the
@@ -16533,7 +16906,7 @@ display_line (it)
 
       /* If we truncate lines, we are done when the last displayed
         glyphs reach past the right margin of the window.  */
-      if (it->truncate_lines_p
+      if (it->line_wrap == TRUNCATE
          && (FRAME_WINDOW_P (it->f)
              ? (it->current_x >= it->last_visible_x)
              : (it->current_x > it->last_visible_x)))
@@ -16716,10 +17089,11 @@ display_menu_bar (w)
   if (FRAME_X_P (f))
     return;
 #endif
-#ifdef MAC_OS
-  if (FRAME_MAC_P (f))
+
+#ifdef HAVE_NS
+  if (FRAME_NS_P (f))
     return;
-#endif
+#endif /* HAVE_NS */
 
 #ifdef USE_X_TOOLKIT
   xassert (!FRAME_WINDOW_P (f));
@@ -17589,7 +17963,7 @@ If FACE is an integer, the value string has no text properties.
 Optional third and fourth args WINDOW and BUFFER specify the window
 and buffer to use as the context for the formatting (defaults
 are the selected window and the window's buffer).  */)
-  (format, face, window, buffer)
+     (format, face, window, buffer)
      Lisp_Object format, face, window, buffer;
 {
   struct it it;
@@ -18558,7 +18932,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
        {
          struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
 
-         if (!it->truncate_lines_p
+         if (it->line_wrap != TRUNCATE
              && x + glyph->pixel_width > max_x)
            {
              /* End of continued line or max_x reached.  */
@@ -18614,7 +18988,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
       set_iterator_to_next (it, 1);
 
       /* Stop if truncating at the right edge.  */
-      if (it->truncate_lines_p
+      if (it->line_wrap == TRUNCATE
          && it->current_x >= it->last_visible_x)
        {
          /* Add truncation mark, but don't do it if the line is
@@ -19192,7 +19566,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
       if (code != FONT_INVALID_CODE)
        STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
       else
-       STORE_XCHAR2B (char2b, 0, code);
+       STORE_XCHAR2B (char2b, 0, 0);
     }
 
   /* Make sure X resources of the face are allocated.  */
@@ -19549,7 +19923,7 @@ left_overwriting (s)
 
 
 /* Return the index of the last glyph following glyph string S that is
-   not overwritten by S because of S's right overhang.  Value is -1 if
+   overwritten by S because of S's right overhang.  Value is -1 if
    no such glyph is found.  */
 
 static int
@@ -19886,9 +20260,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
   struct glyph_string *head, *tail;
   struct glyph_string *s;
   struct glyph_string *clip_head = NULL, *clip_tail = NULL;
-  int last_x, area_width;
-  int x_reached;
-  int i, j;
+  int i, j, x_reached, last_x, area_left = 0;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   DECLARE_HDC (hdc);
 
@@ -19905,16 +20277,15 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
     {
       /* X is relative to the left edge of W, without scroll bars
         or fringes.  */
-      x += WINDOW_LEFT_EDGE_X (w);
+      area_left = WINDOW_LEFT_EDGE_X (w);
       last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
     }
   else
     {
-      int area_left = window_box_left (w, area);
-      x += area_left;
-      area_width = window_box_width (w, area);
-      last_x = area_left + area_width;
+      area_left = window_box_left (w, area);
+      last_x = area_left + window_box_width (w, area);
     }
+  x += area_left;
 
   /* Build a doubly-linked list of glyph_string structures between
      head and tail from what we have to draw.  Note that the macro
@@ -19932,8 +20303,30 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
      strings built above.  */
   if (head && !overlaps && row->contains_overlapping_glyphs_p)
     {
-      int dummy_x = 0;
       struct glyph_string *h, *t;
+      Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+      int mouse_beg_col, mouse_end_col, check_mouse_face = 0;
+      int dummy_x = 0;
+
+      /* If mouse highlighting is on, we may need to draw adjacent
+        glyphs using mouse-face highlighting.  */
+      if (area == TEXT_AREA && row->mouse_face_p)
+       {
+         struct glyph_row *mouse_beg_row, *mouse_end_row;
+
+         mouse_beg_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+         mouse_end_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+
+         if (row >= mouse_beg_row && row <= mouse_end_row)
+           {
+             check_mouse_face = 1;
+             mouse_beg_col = (row == mouse_beg_row)
+               ? dpyinfo->mouse_face_beg_col : 0;
+             mouse_end_col = (row == mouse_end_row)
+               ? dpyinfo->mouse_face_end_col
+               : row->used[TEXT_AREA];
+           }
+       }
 
       /* Compute overhangs for all glyph strings.  */
       if (FRAME_RIF (f)->compute_glyph_string_overhangs)
@@ -19948,10 +20341,24 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       i = left_overwritten (head);
       if (i >= 0)
        {
+         enum draw_glyphs_face overlap_hl;
+
+         /* If this row contains mouse highlighting, attempt to draw
+            the overlapped glyphs with the correct highlight.  This
+            code fails if the overlap encompasses more than one glyph
+            and mouse-highlight spans only some of these glyphs.
+            However, making it work perfectly involves a lot more
+            code, and I don't know if the pathological case occurs in
+            practice, so we'll stick to this for now.  --- cyd  */
+         if (check_mouse_face
+             && mouse_beg_col < start && mouse_end_col > i)
+           overlap_hl = DRAW_MOUSE_FACE;
+         else
+           overlap_hl = DRAW_NORMAL_TEXT;
+
          j = i;
          BUILD_GLYPH_STRINGS (j, start, h, t,
-                              DRAW_NORMAL_TEXT, dummy_x, last_x);
-         start = i;
+                              overlap_hl, dummy_x, last_x);
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
          clip_head = head;
@@ -19967,9 +20374,17 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       i = left_overwriting (head);
       if (i >= 0)
        {
+         enum draw_glyphs_face overlap_hl;
+
+         if (check_mouse_face
+             && mouse_beg_col < start && mouse_end_col > i)
+           overlap_hl = DRAW_MOUSE_FACE;
+         else
+           overlap_hl = DRAW_NORMAL_TEXT;
+
          clip_head = head;
          BUILD_GLYPH_STRINGS (i, start, h, t,
-                              DRAW_NORMAL_TEXT, dummy_x, last_x);
+                              overlap_hl, dummy_x, last_x);
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
          compute_overhangs_and_x (t, head->x, 1);
@@ -19983,8 +20398,16 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       i = right_overwritten (tail);
       if (i >= 0)
        {
+         enum draw_glyphs_face overlap_hl;
+
+         if (check_mouse_face
+             && mouse_beg_col < i && mouse_end_col > end)
+           overlap_hl = DRAW_MOUSE_FACE;
+         else
+           overlap_hl = DRAW_NORMAL_TEXT;
+
          BUILD_GLYPH_STRINGS (end, i, h, t,
-                              DRAW_NORMAL_TEXT, x, last_x);
+                              overlap_hl, x, last_x);
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
          clip_tail = tail;
@@ -19998,10 +20421,17 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       i = right_overwriting (tail);
       if (i >= 0)
        {
+         enum draw_glyphs_face overlap_hl;
+         if (check_mouse_face
+             && mouse_beg_col < i && mouse_end_col > end)
+           overlap_hl = DRAW_MOUSE_FACE;
+         else
+           overlap_hl = DRAW_NORMAL_TEXT;
+
          clip_tail = tail;
          i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
-                              DRAW_NORMAL_TEXT, x, last_x);
+                              overlap_hl, x, last_x);
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
@@ -20029,10 +20459,8 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       int x0 = clip_head ? clip_head->x : (head ? head->x : x);
       int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
                : (tail ? tail->x + tail->background_width : x));
-
-      int text_left = window_box_left (w, TEXT_AREA);
-      x0 -= text_left;
-      x1 -= text_left;
+      x0 -= area_left;
+      x1 -= area_left;
 
       notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
                                 row->y, MATRIX_ROW_BOTTOM_Y (row));
@@ -20043,7 +20471,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
   if (row->full_width_p)
     x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
   else
-    x_reached -= window_box_left (w, area);
+    x_reached -= area_left;
 
   RELEASE_HDC (hdc, f);
 
@@ -20098,6 +20526,7 @@ append_glyph (it)
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = CHAR_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20136,6 +20565,7 @@ append_composite_glyph (it)
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = COMPOSITE_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20317,6 +20747,7 @@ produce_image_glyph (it)
          glyph->descent = it->descent;
          glyph->voffset = it->voffset;
          glyph->type = IMAGE_GLYPH;
+         glyph->avoid_cursor_p = it->avoid_cursor_p;
          glyph->multibyte_p = it->multibyte_p;
          glyph->left_box_line_p = it->start_of_box_run_p;
          glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20361,6 +20792,7 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->descent = height - ascent;
       glyph->voffset = it->voffset;
       glyph->type = STRETCH_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20508,7 +20940,7 @@ produce_stretch_glyph (it)
   else
     ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
 
-  if (width > 0 && !it->truncate_lines_p
+  if (width > 0 && it->line_wrap != TRUNCATE
       && it->current_x + width > it->last_visible_x)
     width = it->last_visible_x - it->current_x - 1;
 
@@ -20528,27 +20960,6 @@ produce_stretch_glyph (it)
   take_vertical_position_into_account (it);
 }
 
-/* Get line-height and line-spacing property at point.
-   If line-height has format (HEIGHT TOTAL), return TOTAL
-   in TOTAL_HEIGHT.  */
-
-static Lisp_Object
-get_line_height_property (it, prop)
-     struct it *it;
-     Lisp_Object prop;
-{
-  Lisp_Object position;
-
-  if (STRINGP (it->object))
-    position = make_number (IT_STRING_CHARPOS (*it));
-  else if (BUFFERP (it->object))
-    position = make_number (IT_CHARPOS (*it));
-  else
-    return Qnil;
-
-  return Fget_char_property (position, prop, it->object);
-}
-
 /* Calculate line-height and line-spacing properties.
    An integer value specifies explicit pixel value.
    A float value specifies relative value to current face height.
@@ -20836,7 +21247,7 @@ x_produce_glyphs (it)
          it->pixel_width = 0;
          it->nglyphs = 0;
 
-         height = get_line_height_property(it, Qline_height);
+         height = get_it_property(it, Qline_height);
          /* Split (line-height total-height) list */
          if (CONSP (height)
              && CONSP (XCDR (height))
@@ -20898,7 +21309,7 @@ x_produce_glyphs (it)
                spacing = calc_line_height_property(it, total_height, font, boff, 0);
              else
                {
-                 spacing = get_line_height_property(it, Qline_spacing);
+                 spacing = get_it_property(it, Qline_spacing);
                  spacing = calc_line_height_property(it, spacing, font, boff, 0);
                }
              if (INTEGERP (spacing))
@@ -20911,25 +21322,33 @@ x_produce_glyphs (it)
        }
       else if (it->char_to_display == '\t')
        {
-         int tab_width = it->tab_width * FRAME_SPACE_WIDTH (it->f);
-         int x = it->current_x + it->continuation_lines_width;
-         int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
-
-         /* If the distance from the current position to the next tab
-            stop is less than a space character width, use the
-            tab stop after that.  */
-         if (next_tab_x - x < FRAME_SPACE_WIDTH (it->f))
-           next_tab_x += tab_width;
-
-         it->pixel_width = next_tab_x - x;
-         it->nglyphs = 1;
-         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
-         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
-
-         if (it->glyph_row)
+         if (font->space_width > 0)
            {
-             append_stretch_glyph (it, it->object, it->pixel_width,
-                                   it->ascent + it->descent, it->ascent);
+             int tab_width = it->tab_width * font->space_width;
+             int x = it->current_x + it->continuation_lines_width;
+             int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+
+             /* If the distance from the current position to the next tab
+                stop is less than a space character width, use the
+                tab stop after that.  */
+             if (next_tab_x - x < font->space_width)
+               next_tab_x += tab_width;
+
+             it->pixel_width = next_tab_x - x;
+             it->nglyphs = 1;
+             it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+             it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+             if (it->glyph_row)
+               {
+                 append_stretch_glyph (it, it->object, it->pixel_width,
+                                       it->ascent + it->descent, it->ascent);
+               }
+           }
+         else
+           {
+             it->pixel_width = 0;
+             it->nglyphs = 1;
            }
        }
       else
@@ -21402,7 +21821,7 @@ x_write_glyphs (start, len)
 
 
 /* EXPORT for RIF:
-   Insert LEN glyphs from START at the nominal cursor position.   */
+   Insert LEN glyphs from START at the nominal cursor position.  */
 
 void
 x_insert_glyphs (start, len)
@@ -22151,7 +22570,10 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
 /* Switch the display of W's cursor on or off, according to the value
    of ON.  */
 
-static void
+#ifndef HAVE_NS
+static
+#endif
+void
 update_window_cursor (w, on)
      struct window *w;
      int on;
@@ -22370,9 +22792,7 @@ cursor_in_mouse_face_p (w)
         in 20.x as well, and I think it's too risky to install
         so near the release of 21.1.  2001-09-25 gerd.  */
 
-#ifndef HAVE_CARBON
 static
-#endif
 int
 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
      struct window *w;
@@ -22770,7 +23190,7 @@ and the radius of the circle; r may be a float or integer.
 A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
 vector describes one corner in the polygon.
 Returns the alist element for the first matching AREA in MAP.  */)
-  (map, x, y)
+     (map, x, y)
      Lisp_Object map;
      Lisp_Object x, y;
 {
@@ -23084,7 +23504,7 @@ note_mouse_highlight (f, x, y)
   struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd.  */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
   if (popup_activated ())
     return;
 #endif
@@ -24442,7 +24862,7 @@ If you want scrolling to always be a line at a time, you should set
     doc: /* *Scroll up to this many lines, to bring point back on screen.
 If point moves off-screen, redisplay will scroll by up to
 `scroll-conservatively' lines in order to bring point just barely
-onto the screen again.   If that cannot be done, then redisplay
+onto the screen again.  If that cannot be done, then redisplay
 recenters point as usual.
 
 A value of zero means always recenter point if it moves off screen.  */);
@@ -24463,11 +24883,18 @@ Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI).  */);
   DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask.  */);
 #endif
 
-  DEFVAR_BOOL ("truncate-partial-width-windows",
-              &truncate_partial_width_windows,
-    doc: /* *Non-nil means truncate lines in all windows less than full frame wide.
-Nil means to respect the value of `truncate-lines'.  */);
-  truncate_partial_width_windows = 1;
+  DEFVAR_LISP ("truncate-partial-width-windows",
+              &Vtruncate_partial_width_windows,
+    doc: /* Non-nil means truncate lines in windows with less than the frame width.
+For an integer value, truncate lines in each window with less than the
+full frame width, provided the window width is less than that integer;
+otherwise, respect the value of `truncate-lines'.
+
+For any other non-nil value, truncate lines in all windows with
+less than the full frame width.
+
+A value of nil means to respect the value of `truncate-lines'.  */);
+  Vtruncate_partial_width_windows = make_number (30);
 
   DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
     doc: /* When nil, display the mode-line/header-line/menu-bar in the default face.
@@ -24705,6 +25132,32 @@ The enable predicate for a menu binding should check this variable.  */);
     doc: /* Non-nil means don't update menu bars.  Internal use only.  */);
   inhibit_menubar_update = 0;
 
+  DEFVAR_LISP ("wrap-prefix", &Vwrap_prefix,
+    doc: /* Prefix added to the beginning of all continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `wrap-prefix' text-property.
+
+To add a prefix to non-continuation lines, use the `line-prefix' variable.  */);
+  Vwrap_prefix = Qnil;
+  staticpro (&Qwrap_prefix);
+  Qwrap_prefix = intern ("wrap-prefix");
+  Fmake_variable_buffer_local (Qwrap_prefix);
+
+  DEFVAR_LISP ("line-prefix", &Vline_prefix,
+    doc: /* Prefix added to the beginning of all non-continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `line-prefix' text-property.
+
+To add a prefix to continuation lines, use the `wrap-prefix' variable.  */);
+  Vline_prefix = Qnil;
+  staticpro (&Qline_prefix);
+  Qline_prefix = intern ("line-prefix");
+  Fmake_variable_buffer_local (Qline_prefix);
+
   DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
     doc: /* Non-nil means don't eval Lisp during redisplay.  */);
   inhibit_eval_during_redisplay = 0;
@@ -24732,6 +25185,27 @@ The enable predicate for a menu binding should check this variable.  */);
 The default value is 2: the height of the overline (1 pixel) plus 1 pixel
 margin to the caracter height.  */);
   overline_margin = 2;
+
+  DEFVAR_INT ("underline-minimum-offset",
+              &underline_minimum_offset,
+     doc: /* Minimum distance between baseline and underline.
+This can improve legibility of underlined text at small font sizes,
+particularly when using variable `x-use-underline-position-properties'
+with fonts that specify an UNDERLINE_POSITION relatively close to the
+baseline.  The default value is 1.  */);
+  underline_minimum_offset = 1;
+
+  DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
+              doc: /* Non-zero means Emacs displays an hourglass pointer on window systems.  */);
+  display_hourglass_p = 1;
+
+  DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
+              doc: /* *Seconds to wait before displaying an hourglass pointer.
+Value must be an integer or float.  */);
+  Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
+
+  hourglass_atimer = NULL;
+  hourglass_shown_p = 0;
 }
 
 
@@ -24787,6 +25261,67 @@ init_xdisp ()
   help_echo_showing_p = 0;
 }
 
+/* Since w32 does not support atimers, it defines its own implementation of
+   the following three functions in w32fns.c.  */
+#ifndef WINDOWSNT
+
+/* Platform-independent portion of hourglass implementation. */
+
+/* Return non-zero if houglass timer has been started or hourglass is shown.  */
+int
+hourglass_started ()
+{
+  return hourglass_shown_p || hourglass_atimer != NULL;
+}
+
+/* Cancel a currently active hourglass timer, and start a new one.  */
+void
+start_hourglass ()
+{
+#if defined (HAVE_WINDOW_SYSTEM)
+  EMACS_TIME delay;
+  int secs, usecs = 0;
+
+  cancel_hourglass ();
+
+  if (INTEGERP (Vhourglass_delay)
+      && XINT (Vhourglass_delay) > 0)
+    secs = XFASTINT (Vhourglass_delay);
+  else if (FLOATP (Vhourglass_delay)
+          && XFLOAT_DATA (Vhourglass_delay) > 0)
+    {
+      Lisp_Object tem;
+      tem = Ftruncate (Vhourglass_delay, Qnil);
+      secs = XFASTINT (tem);
+      usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
+    }
+  else
+    secs = DEFAULT_HOURGLASS_DELAY;
+
+  EMACS_SET_SECS_USECS (delay, secs, usecs);
+  hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
+                                  show_hourglass, NULL);
+#endif
+}
+
+
+/* Cancel the hourglass cursor timer if active, hide a busy cursor if
+   shown.  */
+void
+cancel_hourglass ()
+{
+#if defined (HAVE_WINDOW_SYSTEM)
+  if (hourglass_atimer)
+    {
+      cancel_atimer (hourglass_atimer);
+      hourglass_atimer = NULL;
+    }
+
+  if (hourglass_shown_p)
+    hide_hourglass ();
+#endif
+}
+#endif /* ! WINDOWSNT  */
 
 /* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
    (do not change this comment) */