]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Update copyright year to 2015
[gnu-emacs] / src / xdisp.c
index bf73de69669e8e9b3990174f58f278d52bda2872..aa5bfcbcbe423bdaf1336aa5ddca3216657b4055 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2015 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -347,7 +347,7 @@ Lisp_Object Qtext;
 /* Holds the list (error).  */
 static Lisp_Object list_of_error;
 
-static Lisp_Object Qfontification_functions;
+Lisp_Object Qfontification_functions;
 
 static Lisp_Object Qwrap_prefix;
 static Lisp_Object Qline_prefix;
@@ -905,7 +905,7 @@ static void iterate_out_of_display_property (struct it *);
 static void pop_it (struct it *);
 static void sync_frame_with_window_matrix_rows (struct window *);
 static void redisplay_internal (void);
-static int echo_area_display (int);
+static bool echo_area_display (bool);
 static void redisplay_windows (Lisp_Object);
 static void redisplay_window (Lisp_Object, bool);
 static Lisp_Object redisplay_window_error (Lisp_Object);
@@ -1406,6 +1406,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   struct text_pos top;
   int visible_p = 0;
   struct buffer *old_buffer = NULL;
+  bool r2l = false;
 
   if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
@@ -1691,6 +1692,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
          *rowh = max (0, (min (bottom_y, it.last_visible_y)
                           - max (top_y, window_top_y)));
          *vpos = it.vpos;
+         if (it.bidi_it.paragraph_dir == R2L)
+           r2l = true;
        }
     }
   else
@@ -1720,6 +1723,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
                           - max (it2.current_y,
                                  WINDOW_HEADER_LINE_HEIGHT (w))));
          *vpos = it2.vpos;
+         if (it2.bidi_it.paragraph_dir == R2L)
+           r2l = true;
        }
       else
        bidi_unshelve_cache (it2data, 1);
@@ -1729,10 +1734,20 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
 
-  if (visible_p && w->hscroll > 0)
-    *x -=
-      window_hscroll_limited (w, WINDOW_XFRAME (w))
-      * WINDOW_FRAME_COLUMN_WIDTH (w);
+  if (visible_p)
+    {
+      if (w->hscroll > 0)
+       *x -=
+         window_hscroll_limited (w, WINDOW_XFRAME (w))
+         * WINDOW_FRAME_COLUMN_WIDTH (w);
+      /* For lines in an R2L paragraph, we need to mirror the X pixel
+         coordinate wrt the text area.  For the reasons, see the
+         commentary in buffer_posn_from_coords and the explanation of
+         the geometry used by the move_it_* functions at the end of
+         the large commentary near the beginning of this file.  */
+      if (r2l)
+       *x = window_box_width (w, TEXT_AREA) - *x - 1;
+    }
 
 #if 0
   /* Debugging code.  */
@@ -2302,10 +2317,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
      glyph, and `x-stretch-block-cursor' is nil, don't draw a
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
-  wd = glyph->pixel_width - 1;
-#if defined (HAVE_NTGUI) || defined (HAVE_NS)
-  wd++; /* Why? */
-#endif
+  wd = glyph->pixel_width;
 
   x = w->phys_cursor.x;
   if (x < 0)
@@ -5109,6 +5121,11 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                  iterate_out_of_display_property (it);
                  *position = it->position;
                }
+             /* If we were to display this fringe bitmap,
+                next_element_from_image would have reset this flag.
+                Do the same, to avoid affecting overlays that
+                follow.  */
+             it->ignore_overlay_strings_at_pos_p = 0;
              return 1;
            }
        }
@@ -5128,6 +5145,9 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
              iterate_out_of_display_property (it);
              *position = it->position;
            }
+         if (it)
+           /* Reset this flag like next_element_from_image would.  */
+           it->ignore_overlay_strings_at_pos_p = 0;
          return 1;
        }
 
@@ -6935,7 +6955,8 @@ get_next_display_element (struct it *it)
         is R..."  */
       /* FIXME: Do we need an exception for characters from display
         tables?  */
-      if (it->bidi_p && it->bidi_it.type == STRONG_R)
+      if (it->bidi_p && it->bidi_it.type == STRONG_R
+         && !inhibit_bidi_mirroring)
        it->c = bidi_mirror_char (it->c);
       /* Map via display table or translate control characters.
         IT->c, IT->len etc. have been set to the next character by
@@ -7326,27 +7347,15 @@ set_iterator_to_next (struct it *it, int reseat_p)
       else if (it->cmp_it.id >= 0)
        {
          /* We are currently getting glyphs from a composition.  */
-         int i;
-
          if (! it->bidi_p)
            {
              IT_CHARPOS (*it) += it->cmp_it.nchars;
              IT_BYTEPOS (*it) += it->cmp_it.nbytes;
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               {
-                 it->cmp_it.from = it->cmp_it.to;
-               }
-             else
-               {
-                 it->cmp_it.id = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it),
-                                               it->end_charpos, Qnil);
-               }
            }
-         else if (! it->cmp_it.reversed_p)
+         else
            {
-             /* Composition created while scanning forward.  */
+             int i;
+
              /* Update IT's char/byte positions to point to the first
                 character of the next grapheme cluster, or to the
                 character visually after the current composition.  */
@@ -7354,52 +7363,34 @@ set_iterator_to_next (struct it *it, int reseat_p)
                bidi_move_to_visually_next (&it->bidi_it);
              IT_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_CHARPOS (*it) = it->bidi_it.charpos;
+           }
 
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               {
-                 /* Proceed to the next grapheme cluster.  */
-                 it->cmp_it.from = it->cmp_it.to;
-               }
-             else
-               {
-                 /* No more grapheme clusters in this composition.
-                    Find the next stop position.  */
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   /* Now we are scanning backward and don't know
-                      where to stop.  */
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it), stop, Qnil);
-               }
+         if ((! it->bidi_p || ! it->cmp_it.reversed_p)
+             && it->cmp_it.to < it->cmp_it.nglyphs)
+           {
+             /* Composition created while scanning forward.  Proceed
+                to the next grapheme cluster.  */
+             it->cmp_it.from = it->cmp_it.to;
+           }
+         else if ((it->bidi_p && it->cmp_it.reversed_p)
+                  && it->cmp_it.from > 0)
+           {
+             /* Composition created while scanning backward.  Proceed
+                to the previous grapheme cluster.  */
+             it->cmp_it.to = it->cmp_it.from;
            }
          else
            {
-             /* Composition created while scanning backward.  */
-             /* Update IT's char/byte positions to point to the last
-                character of the previous grapheme cluster, or the
-                character visually after the current composition.  */
-             for (i = 0; i < it->cmp_it.nchars; i++)
-               bidi_move_to_visually_next (&it->bidi_it);
-             IT_BYTEPOS (*it) = it->bidi_it.bytepos;
-             IT_CHARPOS (*it) = it->bidi_it.charpos;
-             if (it->cmp_it.from > 0)
-               {
-                 /* Proceed to the previous grapheme cluster.  */
-                 it->cmp_it.to = it->cmp_it.from;
-               }
-             else
-               {
-                 /* No more grapheme clusters in this composition.
-                    Find the next stop position.  */
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   /* Now we are scanning backward and don't know
-                      where to stop.  */
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
-                                               IT_BYTEPOS (*it), stop, Qnil);
-               }
+             /* No more grapheme clusters in this composition.
+                Find the next stop position.  */
+             ptrdiff_t stop = it->end_charpos;
+
+             if (it->bidi_it.scan_dir < 0)
+               /* Now we are scanning backward and don't know
+                  where to stop.  */
+               stop = -1;
+             composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
+                                           IT_BYTEPOS (*it), stop, Qnil);
            }
        }
       else
@@ -7528,61 +7519,63 @@ set_iterator_to_next (struct it *it, int reseat_p)
        }
       if (it->cmp_it.id >= 0)
        {
-         int i;
-
+         /* We are delivering display elements from a composition.
+            Update the string position past the grapheme cluster
+            we've just processed.  */
          if (! it->bidi_p)
            {
              IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
              IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               it->cmp_it.from = it->cmp_it.to;
-             else
-               {
-                 it->cmp_it.id = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it),
-                                               it->end_charpos, it->string);
-               }
            }
-         else if (! it->cmp_it.reversed_p)
+         else
            {
+             int i;
+
              for (i = 0; i < it->cmp_it.nchars; i++)
                bidi_move_to_visually_next (&it->bidi_it);
              IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+           }
 
-             if (it->cmp_it.to < it->cmp_it.nglyphs)
-               it->cmp_it.from = it->cmp_it.to;
-             else
-               {
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it), stop,
-                                               it->string);
-               }
+         /* Did we exhaust all the grapheme clusters of this
+            composition?  */
+         if ((! it->bidi_p || ! it->cmp_it.reversed_p)
+             && (it->cmp_it.to < it->cmp_it.nglyphs))
+           {
+             /* Not all the grapheme clusters were processed yet;
+                advance to the next cluster.  */
+             it->cmp_it.from = it->cmp_it.to;
+           }
+         else if ((it->bidi_p && it->cmp_it.reversed_p)
+                  && it->cmp_it.from > 0)
+           {
+             /* Likewise: advance to the next cluster, but going in
+                the reverse direction.  */
+             it->cmp_it.to = it->cmp_it.from;
            }
          else
            {
-             for (i = 0; i < it->cmp_it.nchars; i++)
-               bidi_move_to_visually_next (&it->bidi_it);
-             IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
-             IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
-             if (it->cmp_it.from > 0)
-               it->cmp_it.to = it->cmp_it.from;
-             else
+             /* This composition was fully processed; find the next
+                candidate place for checking for composed
+                characters.  */
+             /* Always limit string searches to the string length;
+                any padding spaces are not part of the string, and
+                there cannot be any compositions in that padding.  */
+             ptrdiff_t stop = SCHARS (it->string);
+
+             if (it->bidi_p && it->bidi_it.scan_dir < 0)
+               stop = -1;
+             else if (it->end_charpos < stop)
                {
-                 ptrdiff_t stop = it->end_charpos;
-                 if (it->bidi_it.scan_dir < 0)
-                   stop = -1;
-                 composition_compute_stop_pos (&it->cmp_it,
-                                               IT_STRING_CHARPOS (*it),
-                                               IT_STRING_BYTEPOS (*it), stop,
-                                               it->string);
+                 /* Cf. PRECISION in reseat_to_string: we might be
+                    limited in how many of the string characters we
+                    need to deliver.  */
+                 stop = it->end_charpos;
                }
+             composition_compute_stop_pos (&it->cmp_it,
+                                           IT_STRING_CHARPOS (*it),
+                                           IT_STRING_BYTEPOS (*it), stop,
+                                           it->string);
            }
        }
       else
@@ -7605,12 +7598,17 @@ set_iterator_to_next (struct it *it, int reseat_p)
              bidi_move_to_visually_next (&it->bidi_it);
              IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
              IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
+             /* If the scan direction changes, we may need to update
+                the place where to check for composed characters.  */
              if (prev_scan_dir != it->bidi_it.scan_dir)
                {
-                 ptrdiff_t stop = it->end_charpos;
+                 ptrdiff_t stop = SCHARS (it->string);
 
                  if (it->bidi_it.scan_dir < 0)
                    stop = -1;
+                 else if (it->end_charpos < stop)
+                   stop = it->end_charpos;
+
                  composition_compute_stop_pos (&it->cmp_it,
                                                IT_STRING_CHARPOS (*it),
                                                IT_STRING_BYTEPOS (*it), stop,
@@ -8331,6 +8329,10 @@ next_element_from_buffer (struct it *it)
       unsigned char *p;
       ptrdiff_t stop;
 
+      /* We moved to the next buffer position, so any info about
+        previously seen overlays is no longer valid.  */
+      it->ignore_overlay_strings_at_pos_p = 0;
+
       /* Maybe run the redisplay end trigger hook.  Performance note:
         This doesn't seem to cost measurable time.  */
       if (it->redisplay_end_trigger_charpos
@@ -8784,12 +8786,7 @@ move_it_in_display_line_to (struct it *it,
                         doesn't fit on the line, e.g. a wide image.  */
                      it->hpos == 0
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f)
-                         /* When word-wrap is ON and we have a valid
-                            wrap point, we don't allow the last glyph
-                            to "just barely fit" on the line.  */
-                         && (it->line_wrap != WORD_WRAP
-                             || wrap_it.sp < 0)))
+                         && FRAME_WINDOW_P (it->f)))
                    {
                      ++it->hpos;
                      it->current_x = new_x;
@@ -8856,7 +8853,8 @@ move_it_in_display_line_to (struct it *it,
                                }
                              if (ITERATOR_AT_END_OF_LINE_P (it)
                                  && (it->line_wrap != WORD_WRAP
-                                     || wrap_it.sp < 0))
+                                     || wrap_it.sp < 0
+                                     || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
                                {
                                  result = MOVE_NEWLINE_OR_CR;
                                  break;
@@ -10269,9 +10267,9 @@ message3_nolog (Lisp_Object m)
       else
        clear_message (true, true);
 
-      do_pending_window_change (0);
-      echo_area_display (1);
-      do_pending_window_change (0);
+      do_pending_window_change (false);
+      echo_area_display (true);
+      do_pending_window_change (false);
       if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
        (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
     }
@@ -11242,13 +11240,13 @@ clear_garbaged_frames (void)
    is non-zero update selected_frame.  Value is non-zero if the
    mini-windows height has been changed.  */
 
-static int
-echo_area_display (int update_frame_p)
+static bool
+echo_area_display (bool update_frame_p)
 {
   Lisp_Object mini_window;
   struct window *w;
   struct frame *f;
-  int window_height_changed_p = 0;
+  bool window_height_changed_p = false;
   struct frame *sf = SELECTED_FRAME ();
 
   mini_window = FRAME_MINIBUF_WINDOW (sf);
@@ -11311,11 +11309,11 @@ echo_area_display (int update_frame_p)
              /* Window configuration is the same as before.
                 Can do with a display update of the echo area,
                 unless we displayed some mode lines.  */
-             update_single_window (w, 1);
+             update_single_window (w);
              flush_frame (f);
            }
          else
-           update_frame (f, 1, 1);
+           update_frame (f, true, true);
 
          /* If cursor is in the echo area, make sure that the next
             redisplay displays the minibuffer, so that the cursor will
@@ -11786,12 +11784,6 @@ prepare_menu_bars (void)
          menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
 #ifdef HAVE_WINDOW_SYSTEM
          update_tool_bar (f, 0);
-#endif
-#ifdef HAVE_NS
-          if (windows_or_buffers_changed
-             && FRAME_NS_P (f))
-            ns_set_doc_edited
-             (f, Fbuffer_modified_p (XWINDOW (f->selected_window)->contents));
 #endif
          UNGCPRO;
        }
@@ -13435,7 +13427,7 @@ redisplay_internal (void)
   struct window *w = XWINDOW (selected_window);
   struct window *sw;
   struct frame *fr;
-  int pending;
+  bool pending;
   bool must_finish = 0, match_p;
   struct text_pos tlbufpos, tlendpos;
   int number_of_visible_frames;
@@ -13495,7 +13487,7 @@ redisplay_internal (void)
   /* Remember the currently selected window.  */
   sw = w;
 
-  pending = 0;
+  pending = false;
   last_escape_glyph_frame = NULL;
   last_escape_glyph_face_id = (1 << FACE_ID_BITS);
   last_glyphless_glyph_frame = NULL;
@@ -13547,7 +13539,7 @@ redisplay_internal (void)
     }
 
   /* Notice any pending interrupt request to change frame size.  */
-  do_pending_window_change (1);
+  do_pending_window_change (true);
 
   /* do_pending_window_change could change the selected_window due to
      frame resizing which makes the selected window too small.  */
@@ -13594,7 +13586,7 @@ redisplay_internal (void)
             echo-area doesn't show through.  */
          && !MINI_WINDOW_P (XWINDOW (selected_window))))
     {
-      int window_height_changed_p = echo_area_display (0);
+      int window_height_changed_p = echo_area_display (false);
 
       if (message_cleared_p)
        update_miniwindow_p = true;
@@ -13802,7 +13794,7 @@ redisplay_internal (void)
        {
          if (!must_finish)
            {
-             do_pending_window_change (1);
+             do_pending_window_change (true);
              /* If selected_window changed, redisplay again.  */
              if (WINDOWP (selected_window)
                  && (w = XWINDOW (selected_window)) != sw)
@@ -13919,14 +13911,14 @@ redisplay_internal (void)
                  if (f->fonts_changed)
                    {
                      adjust_frame_glyphs (f);
-                     f->fonts_changed = 0;
+                     f->fonts_changed = false;
                      goto retry_frame;
                    }
 
                  /* See if we have to hscroll.  */
                  if (!f->already_hscrolled_p)
                    {
-                     f->already_hscrolled_p = 1;
+                     f->already_hscrolled_p = true;
                      if (hscroll_windows (f->root_window))
                        goto retry_frame;
                    }
@@ -13938,9 +13930,9 @@ redisplay_internal (void)
                    unrequest_sigio ();
                  STOP_POLLING;
 
-                 pending |= update_frame (f, 0, 0);
-                 f->cursor_type_changed = 0;
-                 f->updated_p = 1;
+                 pending |= update_frame (f, false, false);
+                 f->cursor_type_changed = false;
+                 f->updated_p = true;
                }
            }
        }
@@ -14001,8 +13993,8 @@ redisplay_internal (void)
            goto retry;
 
          XWINDOW (selected_window)->must_be_updated_p = true;
-         pending = update_frame (sf, 0, 0);
-         sf->cursor_type_changed = 0;
+         pending = update_frame (sf, false, false);
+         sf->cursor_type_changed = false;
        }
 
       /* We may have called echo_area_display at the top of this
@@ -14016,8 +14008,8 @@ redisplay_internal (void)
       if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
        {
          XWINDOW (mini_window)->must_be_updated_p = true;
-         pending |= update_frame (mini_frame, 0, 0);
-         mini_frame->cursor_type_changed = 0;
+         pending |= update_frame (mini_frame, false, false);
+         mini_frame->cursor_type_changed = false;
          if (!pending && hscroll_windows (mini_window))
            goto retry;
        }
@@ -14094,7 +14086,7 @@ redisplay_internal (void)
     }
 
   /* Change frame size now if a change is pending.  */
-  do_pending_window_change (1);
+  do_pending_window_change (true);
 
   /* If we just did a pending size change, or have additional
      visible frames, or selected_window changed, redisplay again.  */
@@ -14110,7 +14102,7 @@ redisplay_internal (void)
 
   if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
     {
-      clear_face_cache (0);
+      clear_face_cache (false);
       clear_face_cache_count = 0;
     }
 
@@ -14123,6 +14115,9 @@ redisplay_internal (void)
 #endif /* HAVE_WINDOW_SYSTEM */
 
  end_of_redisplay:
+#ifdef HAVE_NS
+  ns_set_doc_edited ();
+#endif
   if (interrupt_input && interrupts_deferred)
     request_sigio ();
 
@@ -14151,9 +14146,9 @@ redisplay_preserve_echo_area (int from_where)
     {
       /* We have a previously displayed message, but no current
         message.  Redisplay the previous message.  */
-      display_last_displayed_message_p = 1;
+      display_last_displayed_message_p = true;
       redisplay_internal ();
-      display_last_displayed_message_p = 0;
+      display_last_displayed_message_p = false;
     }
   else
     redisplay_internal ();
@@ -15201,8 +15196,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                 non-zero margins, because scroll_up_aggressively
                 means put point that fraction of window height
                 _from_the_bottom_margin_.  */
-             if (aggressive_scroll + 2*this_scroll_margin > height)
-               aggressive_scroll = height - 2*this_scroll_margin;
+             if (aggressive_scroll + 2 * this_scroll_margin > height)
+               aggressive_scroll = height - 2 * this_scroll_margin;
              amount_to_scroll = dy + aggressive_scroll;
            }
        }
@@ -15295,8 +15290,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          start_display (&it, w, startp);
 
          if (arg_scroll_conservatively)
-           amount_to_scroll = max (dy, frame_line_height *
-                                   max (scroll_step, temp_scroll_step));
+           amount_to_scroll = max (dy, frame_line_height
+                                   max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
@@ -15313,8 +15308,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
                     bottom of the window, if the value of
                     scroll_down_aggressively happens to be too
                     large.  */
-                 if (aggressive_scroll + 2*this_scroll_margin > height)
-                   aggressive_scroll = height - 2*this_scroll_margin;
+                 if (aggressive_scroll + 2 * this_scroll_margin > height)
+                   aggressive_scroll = height - 2 * this_scroll_margin;
                  amount_to_scroll = dy + aggressive_scroll;
                }
            }
@@ -16347,16 +16342,24 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
          set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
 
-         /* If we are highlighting the region, then we just changed
-            the region, so redisplay to show it.  */
-         /* FIXME: We need to (re)run pre-redisplay-function!  */
-         /* if (markpos_of_region () >= 0)
+         /* Re-run pre-redisplay-function so it can update the region
+            according to the new position of point.  */
+         /* Other than the cursor, w's redisplay is done so we can set its
+            redisplay to false.  Also the buffer's redisplay can be set to
+            false, since propagate_buffer_redisplay should have already
+            propagated its info to `w' anyway.  */
+         w->redisplay = false;
+         XBUFFER (w->contents)->text->redisplay = false;
+         safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
+
+         if (w->redisplay || XBUFFER (w->contents)->text->redisplay)
            {
+             /* pre-redisplay-function made changes (e.g. move the region)
+                that require another round of redisplay.  */
              clear_glyph_matrix (w->desired_matrix);
              if (!try_window (window, startp, 0))
                goto need_larger_matrices;
            }
-         */
        }
       if (w->cursor.vpos < 0 || !cursor_row_fully_visible_p (w, 0, 0))
        {
@@ -16577,8 +16580,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
     {
       int window_total_lines
        = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
-      int margin =
-       scroll_margin > 0
+      int margin
+       scroll_margin > 0
        ? min (scroll_margin, window_total_lines / 4)
        : 0;
       ptrdiff_t margin_pos = CHARPOS (startp);
@@ -18800,7 +18803,10 @@ DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
        doc: /* Dump the current matrix of the selected window to stderr.
 Shows contents of glyph row structures.  With non-nil
 parameter GLYPHS, dump glyphs as well.  If GLYPHS is 1 show
-glyphs in short form, otherwise show glyphs in long form.  */)
+glyphs in short form, otherwise show glyphs in long form.
+
+Interactively, no argument means show glyphs in short form;
+with numeric argument, its value is passed as the GLYPHS flag.  */)
   (Lisp_Object glyphs)
 {
   struct window *w = XWINDOW (selected_window);
@@ -18818,11 +18824,16 @@ glyphs in short form, otherwise show glyphs in long form.  */)
 
 
 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
-       Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
+       Sdump_frame_glyph_matrix, 0, 0, "", doc: /* Dump the current glyph matrix of the selected frame to stderr.
+Only text-mode frames have frame glyph matrices.  */)
   (void)
 {
   struct frame *f = XFRAME (selected_frame);
-  dump_glyph_matrix (f->current_matrix, 1);
+
+  if (f->current_matrix)
+    dump_glyph_matrix (f->current_matrix, 1);
+  else
+    fprintf (stderr, "*** This frame doesn't have a frame glyph matrix ***\n");
   return Qnil;
 }
 
@@ -20415,7 +20426,8 @@ display_line (struct it *it)
                        {
                          /* If line-wrap is on, check if a previous
                             wrap point was found.  */
-                         if (wrap_row_used > 0
+                         if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
+                             && wrap_row_used > 0
                              /* Even if there is a previous wrap
                                 point, continue the line here as
                                 usual, if (i) the previous character
@@ -20445,6 +20457,18 @@ display_line (struct it *it)
                                  row->continued_p = 0;
                                  row->exact_window_width_line_p = 1;
                                }
+                             /* If line-wrap is on, check if a
+                                previous wrap point was found.  */
+                             else 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;
+
                            }
                        }
                      else if (it->bidi_p)
@@ -21009,6 +21033,143 @@ See also `bidi-paragraph-direction'.  */)
     }
 }
 
+DEFUN ("bidi-find-overridden-directionality",
+       Fbidi_find_overridden_directionality,
+       Sbidi_find_overridden_directionality, 2, 3, 0,
+       doc: /* Return position between FROM and TO where directionality was overridden.
+
+This function returns the first character position in the specified
+region of OBJECT where there is a character whose `bidi-class' property
+is `L', but which was forced to display as `R' by a directional
+override, and likewise with characters whose `bidi-class' is `R'
+or `AL' that were forced to display as `L'.
+
+If no such character is found, the function returns nil.
+
+OBJECT is a Lisp string or buffer to search for overridden
+directionality, and defaults to the current buffer if nil or omitted.
+OBJECT can also be a window, in which case the function will search
+the buffer displayed in that window.  Passing the window instead of
+a buffer is preferable when the buffer is displayed in some window,
+because this function will then be able to correctly account for
+window-specific overlays, which can affect the results.
+
+Strong directional characters `L', `R', and `AL' can have their
+intrinsic directionality overridden by directional override
+control characters RLO \(u+202e) and LRO \(u+202d).  See the
+function `get-char-code-property' for a way to inquire about
+the `bidi-class' property of a character.  */)
+  (Lisp_Object from, Lisp_Object to, Lisp_Object object)
+{
+  struct buffer *buf = current_buffer;
+  struct buffer *old = buf;
+  struct window *w = NULL;
+  bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
+  struct bidi_it itb;
+  ptrdiff_t from_pos, to_pos, from_bpos;
+  void *itb_data;
+
+  if (!NILP (object))
+    {
+      if (BUFFERP (object))
+       buf = XBUFFER (object);
+      else if (WINDOWP (object))
+       {
+         w = decode_live_window (object);
+         buf = XBUFFER (w->contents);
+         frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
+       }
+      else
+       CHECK_STRING (object);
+    }
+
+  if (STRINGP (object))
+    {
+      /* Characters in unibyte strings are always treated by bidi.c as
+        strong LTR.  */
+      if (!STRING_MULTIBYTE (object)
+         /* When we are loading loadup.el, the character property
+            tables needed for bidi iteration are not yet
+            available.  */
+         || !NILP (Vpurify_flag))
+       return Qnil;
+
+      validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
+      if (from_pos >= SCHARS (object))
+       return Qnil;
+
+      /* Set up the bidi iterator.  */
+      itb_data = bidi_shelve_cache ();
+      itb.paragraph_dir = NEUTRAL_DIR;
+      itb.string.lstring = object;
+      itb.string.s = NULL;
+      itb.string.schars = SCHARS (object);
+      itb.string.bufpos = 0;
+      itb.string.from_disp_str = 0;
+      itb.string.unibyte = 0;
+      itb.w = w;
+      bidi_init_it (0, 0, frame_window_p, &itb);
+    }
+  else
+    {
+      /* Nothing this fancy can happen in unibyte buffers, or in a
+        buffer that disabled reordering, or if FROM is at EOB.  */
+      if (NILP (BVAR (buf, bidi_display_reordering))
+         || NILP (BVAR (buf, enable_multibyte_characters))
+         /* When we are loading loadup.el, the character property
+            tables needed for bidi iteration are not yet
+            available.  */
+         || !NILP (Vpurify_flag))
+       return Qnil;
+
+      set_buffer_temp (buf);
+      validate_region (&from, &to);
+      from_pos = XINT (from);
+      to_pos = XINT (to);
+      if (from_pos >= ZV)
+       return Qnil;
+
+      /* Set up the bidi iterator.  */
+      itb_data = bidi_shelve_cache ();
+      from_bpos = CHAR_TO_BYTE (from_pos);
+      if (from_pos == BEGV)
+       {
+         itb.charpos = BEGV;
+         itb.bytepos = BEGV_BYTE;
+       }
+      else if (FETCH_CHAR (from_bpos - 1) == '\n')
+       {
+         itb.charpos = from_pos;
+         itb.bytepos = from_bpos;
+       }
+      else
+       itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
+                                           -1, &itb.bytepos);
+      itb.paragraph_dir = NEUTRAL_DIR;
+      itb.string.s = NULL;
+      itb.string.lstring = Qnil;
+      itb.string.bufpos = 0;
+      itb.string.from_disp_str = 0;
+      itb.string.unibyte = 0;
+      itb.w = w;
+      bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
+    }
+
+  ptrdiff_t found;
+  do {
+    /* For the purposes of this function, the actual base direction of
+       the paragraph doesn't matter, so just set it to L2R.  */
+    bidi_paragraph_init (L2R, &itb, 0);
+    while ((found = bidi_find_first_overridden (&itb)) < from_pos)
+      ;
+  } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
+
+  bidi_unshelve_cache (itb_data, 0);
+  set_buffer_temp (old);
+
+  return (from_pos <= found && found < to_pos) ? make_number (found) : Qnil;
+}
+
 DEFUN ("move-point-visually", Fmove_point_visually,
        Smove_point_visually, 1, 1, 0,
        doc: /* Move point in the visual order in the specified DIRECTION.
@@ -21468,6 +21629,114 @@ Value is the new character position of point.  */)
 #undef ROW_GLYPH_NEWLINE_P
 }
 
+DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
+       Sbidi_resolved_levels, 0, 1, 0,
+       doc: /* Return the resolved bidirectional levels of characters at VPOS.
+
+The resolved levels are produced by the Emacs bidi reordering engine
+that implements the UBA, the Unicode Bidirectional Algorithm.  Please
+read the Unicode Standard Annex 9 (UAX#9) for background information
+about these levels.
+
+VPOS is the zero-based number of the current window's screen line
+for which to produce the resolved levels.  If VPOS is nil or omitted,
+it defaults to the screen line of point.  If the window displays a
+header line, VPOS of zero will report on the header line, and first
+line of text in the window will have VPOS of 1.
+
+Value is an array of resolved levels, indexed by glyph number.
+Glyphs are numbered from zero starting from the beginning of the
+screen line, i.e. the left edge of the window for left-to-right lines
+and from the right edge for right-to-left lines.  The resolved levels
+are produced only for the window's text area; text in display margins
+is not included.
+
+If the selected window's display is not up-to-date, or if the specified
+screen line does not display text, this function returns nil.  It is
+highly recommended to bind this function to some simple key, like F8,
+in order to avoid these problems.
+
+This function exists mainly for testing the correctness of the
+Emacs UBA implementation, in particular with the test suite.  */)
+  (Lisp_Object vpos)
+{
+  struct window *w = XWINDOW (selected_window);
+  struct buffer *b = XBUFFER (w->contents);
+  int nrow;
+  struct glyph_row *row;
+
+  if (NILP (vpos))
+    {
+      int d1, d2, d3, d4, d5;
+
+      pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
+    }
+  else
+    {
+      CHECK_NUMBER_COERCE_MARKER (vpos);
+      nrow = XINT (vpos);
+    }
+
+  /* We require up-to-date glyph matrix for this window.  */
+  if (w->window_end_valid
+      && !windows_or_buffers_changed
+      && b
+      && !b->clip_changed
+      && !b->prevent_redisplay_optimizations_p
+      && !window_outdated (w)
+      && nrow >= 0
+      && nrow < w->current_matrix->nrows
+      && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
+      && MATRIX_ROW_DISPLAYS_TEXT_P (row))
+    {
+      struct glyph *g, *e, *g1;
+      int nglyphs, i;
+      Lisp_Object levels;
+
+      if (!row->reversed_p)    /* Left-to-right glyph row.  */
+       {
+         g = g1 = row->glyphs[TEXT_AREA];
+         e = g + row->used[TEXT_AREA];
+
+         /* Skip over glyphs at the start of the row that was
+            generated by redisplay for its own needs.  */
+         while (g < e
+                && INTEGERP (g->object)
+                && g->charpos < 0)
+           g++;
+         g1 = g;
+
+         /* Count the "interesting" glyphs in this row.  */
+         for (nglyphs = 0; g < e && !INTEGERP (g->object); g++)
+           nglyphs++;
+
+         /* Create and fill the array.  */
+         levels = make_uninit_vector (nglyphs);
+         for (i = 0; g1 < g; i++, g1++)
+           ASET (levels, i, make_number (g1->resolved_level));
+       }
+      else                     /* Right-to-left glyph row.  */
+       {
+         g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
+         e = row->glyphs[TEXT_AREA] - 1;
+         while (g > e
+                && INTEGERP (g->object)
+                && g->charpos < 0)
+           g--;
+         g1 = g;
+         for (nglyphs = 0; g > e && !INTEGERP (g->object); g--)
+           nglyphs++;
+         levels = make_uninit_vector (nglyphs);
+         for (i = 0; g1 > g; i++, g1--)
+           ASET (levels, i, make_number (g1->resolved_level));
+       }
+      return levels;
+    }
+  else
+    return Qnil;
+}
+
+
 \f
 /***********************************************************************
                               Menu Bar
@@ -25198,8 +25467,7 @@ append_glyph (struct it *it)
       if (it->bidi_p)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
-         if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           emacs_abort ();
+         eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
          glyph->bidi_type = it->bidi_it.type;
        }
       else
@@ -25282,8 +25550,7 @@ append_composite_glyph (struct it *it)
       if (it->bidi_p)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
-         if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           emacs_abort ();
+         eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
          glyph->bidi_type = it->bidi_it.type;
        }
       ++it->glyph_row->used[area];
@@ -25471,8 +25738,7 @@ produce_image_glyph (struct it *it)
          if (it->bidi_p)
            {
              glyph->resolved_level = it->bidi_it.resolved_level;
-             if ((it->bidi_it.type & 7) != it->bidi_it.type)
-               emacs_abort ();
+             eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
              glyph->bidi_type = it->bidi_it.type;
            }
          ++it->glyph_row->used[area];
@@ -25560,8 +25826,7 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
       if (it->bidi_p)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
-         if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           emacs_abort ();
+         eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
          glyph->bidi_type = it->bidi_it.type;
        }
       else
@@ -26020,8 +26285,7 @@ append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len,
       if (it->bidi_p)
        {
          glyph->resolved_level = it->bidi_it.resolved_level;
-         if ((it->bidi_it.type & 7) != it->bidi_it.type)
-           emacs_abort ();
+         eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
          glyph->bidi_type = it->bidi_it.type;
        }
       ++it->glyph_row->used[area];
@@ -27852,7 +28116,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
 
 #ifdef HAVE_WINDOW_SYSTEM
   /* Change the mouse cursor.  */
-  if (FRAME_WINDOW_P (f))
+  if (FRAME_WINDOW_P (f) && NILP (do_mouse_tracking))
     {
 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
       if (draw == DRAW_NORMAL_TEXT
@@ -30335,6 +30599,7 @@ syms_of_xdisp (void)
   defsubr (&Scurrent_bidi_paragraph_direction);
   defsubr (&Swindow_text_pixel_size);
   defsubr (&Smove_point_visually);
+  defsubr (&Sbidi_find_overridden_directionality);
 
   DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
   DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
@@ -30437,6 +30702,7 @@ syms_of_xdisp (void)
 
   DEFSYM (Qright_to_left, "right-to-left");
   DEFSYM (Qleft_to_right, "left-to-right");
+  defsubr (&Sbidi_resolved_levels);
 
 #ifdef HAVE_WINDOW_SYSTEM
   DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
@@ -30616,9 +30882,12 @@ all the functions in the list are called, with the frame as argument.  */);
   DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
     doc: /* List of functions to call before redisplaying a window with scrolling.
 Each function is called with two arguments, the window and its new
-display-start position.  Note that these functions are also called by
-`set-window-buffer'.  Also note that the value of `window-end' is not
-valid when these functions are called.
+display-start position.
+These functions are called whenever the `window-start' marker is modified,
+either to point into another buffer (e.g. via `set-window-buffer') or another
+place in the same buffer.
+Note that the value of `window-end' is not valid when these functions are
+called.
 
 Warning: Do not use this feature to alter the way the window
 is scrolled.  It is not designed for that, and such use probably won't
@@ -30843,6 +31112,12 @@ To add a prefix to continuation lines, use `wrap-prefix'.  */);
     doc: /* Non-nil means don't free realized faces.  Internal use only.  */);
   inhibit_free_realized_faces = 0;
 
+  DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
+    doc: /* Non-nil means don't mirror characters even when bidi context requires that.
+Intended for use during debugging and for testing bidi display;
+see biditest.el in the test suite.  */);
+  inhibit_bidi_mirroring = 0;
+
 #ifdef GLYPH_DEBUG
   DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
               doc: /* Inhibit try_window_id display optimization.  */);