Improve window dividers code.
[bpt/emacs.git] / src / xdisp.c
index b52c89a..0ca877d 100644 (file)
@@ -1,6 +1,7 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2013 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -570,7 +571,7 @@ static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
 
 /* Ascent and height of the last line processed by move_it_to.  */
 
-static int last_max_ascent, last_height;
+static int last_height;
 
 /* Non-zero if there's a help-echo in the echo area.  */
 
@@ -620,7 +621,9 @@ redisplay_other_windows (void)
 void
 wset_redisplay (struct window *w)
 {
-  redisplay_other_windows ();
+  /* Beware: selected_window can be nil during early stages.  */
+  if (!EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
+    redisplay_other_windows ();
   w->redisplay = true;
 }
 
@@ -660,7 +663,7 @@ bset_update_mode_line (struct buffer *b)
 /* Non-zero means print traces of redisplay if compiled with
    GLYPH_DEBUG defined.  */
 
-int trace_redisplay_p;
+bool trace_redisplay_p;
 
 #endif /* GLYPH_DEBUG */
 
@@ -982,7 +985,7 @@ static void append_stretch_glyph (struct it *, Lisp_Object,
 
 static void produce_special_glyphs (struct it *, enum display_element_type);
 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
-static int coords_in_mouse_face_p (struct window *, int, int);
+static bool coords_in_mouse_face_p (struct window *, int, int);
 
 
 \f
@@ -2801,8 +2804,9 @@ init_iterator (struct it *it, struct window *w,
     it->redisplay_end_trigger_charpos
       = marker_position (w->redisplay_end_trigger);
   else if (INTEGERP (w->redisplay_end_trigger))
-    it->redisplay_end_trigger_charpos =
-      clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger), PTRDIFF_MAX);
+    it->redisplay_end_trigger_charpos
+      = clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger),
+                       PTRDIFF_MAX);
 
   it->tab_width = SANE_TAB_WIDTH (current_buffer);
 
@@ -6406,6 +6410,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
       it->bidi_it.string.s = NULL;
       it->bidi_it.string.lstring = Qnil;
       it->bidi_it.string.bufpos = 0;
+      it->bidi_it.string.from_disp_str = 0;
       it->bidi_it.string.unibyte = 0;
       it->bidi_it.w = it->w;
     }
@@ -9094,7 +9099,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       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;
       it->max_ascent = it->max_descent = 0;
     }
 
@@ -9121,7 +9125,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       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;
     }
 
   if (backup_data)
@@ -9467,9 +9470,9 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
     }
 }
 
-/* Return 1 if IT points into the middle of a display vector.  */
+/* Return true if IT points into the middle of a display vector.  */
 
-int
+bool
 in_display_vector_p (struct it *it)
 {
   return (it->method == GET_FROM_DISPLAY_VECTOR
@@ -9506,7 +9509,7 @@ Optional argument MODE_AND_HEADER_LINE nil or omitted means do not
 include the height of the mode- or header-line of WINDOW in the return
 value.  If it is either the symbol `mode-line' or `header-line', include
 only the height of that line, if present, in the return value.  If t,
-include the height of any of these lines in the return value.  */)
+include the height of both, if present, in the return value.  */)
   (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
    Lisp_Object mode_and_header_line)
 {
@@ -9567,20 +9570,19 @@ include the height of any of these lines in the return value.  */)
   if (!NILP (y_limit))
     {
       CHECK_NUMBER (y_limit);
-      max_y = XINT (y_limit);
+      max_y = min (XINT (y_limit), INT_MAX);
     }
 
   itdata = bidi_shelve_cache ();
   SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
   start_display (&it, w, startp);
 
-  /**   move_it_vertically_backward (&it, 0); **/
   if (NILP (x_limit))
     x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
   else
     {
       CHECK_NUMBER (x_limit);
-      it.last_visible_x = XINT (x_limit);
+      it.last_visible_x = min (XINT (x_limit), INFINITY);
       /* Actually, we never want move_it_to stop at to_x.  But to make
         sure that move_it_in_display_line_to always moves far enough,
         we set it to INT_MAX and specify MOVE_TO_X.  */
@@ -9588,14 +9590,7 @@ include the height of any of these lines in the return value.  */)
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
     }
 
-  if (start == end)
-    y = it.current_y;
-  else
-    {
-      /* Count last line.  */
-      last_height = 0;
-      y = line_bottom_y (&it); /* - y; */
-    }
+  y = it.current_y + it.max_ascent + it.max_descent;
 
   if (!EQ (mode_and_header_line, Qheader_line)
       && !EQ (mode_and_header_line, Qt))
@@ -9851,7 +9846,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
         incrementing windows_or_buffers_changed even if *Messages* is
         shown in some window.  So we must manually set
         windows_or_buffers_changed here to make up for that.  */
-       windows_or_buffers_changed = old_windows_or_buffers_changed;
+      windows_or_buffers_changed = old_windows_or_buffers_changed;
       bset_redisplay (current_buffer);
 
       set_buffer_internal (oldbuf);
@@ -10655,9 +10650,9 @@ resize_mini_window (struct window *w, int exact_p)
       /* Compute a suitable window start.  */
       if (height > max_height)
        {
-         height = max_height;
+         height = (max_height / unit) * unit;
          init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
-         move_it_vertically_backward (&it, height);
+         move_it_vertically_backward (&it, height - unit);
          start = it.current.pos;
        }
       else
@@ -11935,7 +11930,9 @@ display_tool_bar_line (struct it *it, int height)
   int max_x = it->last_visible_x;
   struct glyph *last;
 
-  prepare_desired_row (row);
+  /* Don't extend on a previously drawn tool bar items (Bug#16058).  */
+  clear_glyph_row (row);
+  row->enabled_p = true;
   row->y = it->current_y;
 
   /* Note that this isn't made use of if the face hasn't a box,
@@ -12053,8 +12050,8 @@ display_tool_bar_line (struct it *it, int height)
 #define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
   ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
 
-/* Value is the number of screen lines needed to make all tool-bar
-   items of frame F visible.  The number of actual rows needed is
+/* Value is the number of pixels needed to make all tool-bar items of
+   frame F visible.  The actual number of glyph rows needed is
    returned in *N_ROWS if non-NULL.  */
 
 static int
@@ -12071,8 +12068,7 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
-  /* PXW: Use FRAME_PIXEL_WIDTH (f) here?  */
-  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+  it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
   it.paragraph_embedding = L2R;
 
@@ -12105,7 +12101,7 @@ DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
        0, 2, 0,
        doc: /* Return the number of lines occupied by the tool bar of FRAME.
 If FRAME is nil or omitted, use the selected frame.  Optional argument
-PIXELWISE non-nil means return the height of the tool bar inpixels.  */)
+PIXELWISE non-nil means return the height of the tool bar in pixels.  */)
   (Lisp_Object frame, Lisp_Object pixelwise)
 {
   int height = 0;
@@ -12250,6 +12246,10 @@ redisplay_tool_bar (struct frame *f)
          && it.current_y < max_tool_bar_height)
        change_height_p = 1;
 
+      /* We subtract 1 because display_tool_bar_line advances the
+        glyph_row pointer before returning to its caller.  We want to
+        examine the last glyph row produced by
+        display_tool_bar_line.  */
       row = it.glyph_row - 1;
 
       /* If there are blank lines at the end, except for a partially
@@ -12282,18 +12282,35 @@ redisplay_tool_bar (struct frame *f)
 
          if (change_height_p)
            {
+             /* Current size of the tool-bar window in canonical line
+                units.  */
+             int old_lines = WINDOW_TOTAL_LINES (w);
+             /* Required size of the tool-bar window in canonical
+                line units. */
              int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
                               / FRAME_LINE_HEIGHT (f));
-
-             XSETFRAME (frame, f);
-             Fmodify_frame_parameters (frame,
-                                       list1 (Fcons (Qtool_bar_lines,
-                                                     make_number (new_lines))));
-             /* Always do that now.  */
-             clear_glyph_matrix (w->desired_matrix);
-             f->n_tool_bar_rows = nrows;
-             f->fonts_changed = 1;
-             return 1;
+             /* Maximum size of the tool-bar window in canonical line
+                units that this frame can allow. */
+             int max_lines =
+               WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1;
+
+             /* Don't try to change the tool-bar window size and set
+                the fonts_changed flag unless really necessary.  That
+                flag causes redisplay to give up and retry
+                redisplaying the frame from scratch, so setting it
+                unnecessarily can lead to nasty redisplay loops.  */
+             if (new_lines <= max_lines
+                 && eabs (new_lines - old_lines) >= 1)
+               {
+                 XSETFRAME (frame, f);
+                 Fmodify_frame_parameters (frame,
+                                           list1 (Fcons (Qtool_bar_lines,
+                                                         make_number (new_lines))));
+                 clear_glyph_matrix (w->desired_matrix);
+                 f->n_tool_bar_rows = nrows;
+                 f->fonts_changed = 1;
+                 return 1;
+               }
            }
        }
     }
@@ -12603,15 +12620,25 @@ hscroll_window_tree (Lisp_Object window)
        {
          int h_margin;
          int text_area_width;
-         struct glyph_row *current_cursor_row
-           = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
-         struct glyph_row *desired_cursor_row
-           = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
-         struct glyph_row *cursor_row
-           = (desired_cursor_row->enabled_p
-              ? desired_cursor_row
-              : current_cursor_row);
-         int row_r2l_p = cursor_row->reversed_p;
+         struct glyph_row *cursor_row;
+         struct glyph_row *bottom_row;
+         int row_r2l_p;
+
+         bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
+         if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
+           cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
+         else
+           cursor_row = bottom_row - 1;
+
+         if (!cursor_row->enabled_p)
+           {
+             bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
+             if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
+               cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+             else
+               cursor_row = bottom_row - 1;
+           }
+         row_r2l_p = cursor_row->reversed_p;
 
          text_area_width = window_box_width (w, TEXT_AREA);
 
@@ -12767,7 +12794,7 @@ static ptrdiff_t debug_delta, debug_delta_bytes;
 static ptrdiff_t debug_end_vpos;
 
 /* Append a string to W->desired_matrix->method.  FMT is a printf
-   format string.  If trace_redisplay_p is non-zero also printf the
+   format string.  If trace_redisplay_p is true also printf the
    resulting string to stderr.  */
 
 static void debug_method_add (struct window *, char const *, ...)
@@ -13552,7 +13579,7 @@ redisplay_internal (void)
 
     cancel:
       /* Text changed drastically or point moved off of line.  */
-      SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
+      SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
     }
 
   CHARPOS (this_line_start_pos) = 0;
@@ -15586,7 +15613,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       && REDISPLAY_SOME_P ()
       && !w->redisplay
       && !f->redisplay
-      && !buffer->text->redisplay)
+      && !buffer->text->redisplay
+      && BUF_PT (buffer) == w->last_point)
     return;
 
   /* Make sure that both W's markers are valid.  */
@@ -15732,16 +15760,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
      this may be a bit late to catch such changes, but the rest of
      redisplay goes (non-fatally) haywire when the display table is
      changed, so why should we worry about doing any better?  */
-  if (current_buffer->width_run_cache)
+  if (current_buffer->width_run_cache
+      || (current_buffer->base_buffer
+         && current_buffer->base_buffer->width_run_cache))
     {
       struct Lisp_Char_Table *disptab = buffer_display_table ();
 
       if (! disptab_matches_widthtab
          (disptab, XVECTOR (BVAR (current_buffer, width_table))))
         {
-          invalidate_region_cache (current_buffer,
-                                   current_buffer->width_run_cache,
-                                   BEG, Z);
+         struct buffer *buf = current_buffer;
+
+         if (buf->base_buffer)
+           buf = buf->base_buffer;
+          invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
           recompute_width_table (current_buffer, disptab);
         }
     }
@@ -16738,7 +16770,7 @@ try_window_reusing_current_matrix (struct window *w)
 
          /* Disable lines that must be updated.  */
          for (i = 0; i < nrows_scrolled; ++i)
-           (start_row + i)->enabled_p = 0;
+           (start_row + i)->enabled_p = false;
 
          /* Re-compute Y positions.  */
          min_y = WINDOW_HEADER_LINE_HEIGHT (w);
@@ -16918,7 +16950,7 @@ try_window_reusing_current_matrix (struct window *w)
 
       /* Disable rows not reused.  */
       for (row -= nrows_scrolled; row < bottom_row; ++row)
-       row->enabled_p = 0;
+       row->enabled_p = false;
 
       /* Point may have moved to a different line, so we cannot assume that
         the previous cursor position is valid; locate the correct row.  */
@@ -17203,7 +17235,7 @@ sync_frame_with_window_matrix_rows (struct window *w)
       /* Disable frame rows whose corresponding window rows have
         been disabled in try_window_id.  */
       if (!window_row->enabled_p)
-       frame_row->enabled_p = 0;
+       frame_row->enabled_p = false;
 
       ++window_row, ++frame_row;
     }
@@ -17293,9 +17325,16 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
 
    Value is
 
-   1   if display has been updated
-   0   if otherwise unsuccessful
+   >= 1        if successful, i.e. display has been updated
+         specifically:
+         1 means the changes were in front of a newline that precedes
+           the window start, and the whole current matrix was reused
+         2 means the changes were after the last position displayed
+           in the window, and the whole current matrix was reused
+         3 means portions of the current matrix were reused, while
+           some of the screen lines were redrawn
    -1  if redisplay with same window start is known not to succeed
+   0   if otherwise unsuccessful
 
    The following steps are performed:
 
@@ -17370,6 +17409,12 @@ try_window_id (struct window *w)
   if (windows_or_buffers_changed || f->cursor_type_changed)
     GIVE_UP (2);
 
+  /* This function's optimizations cannot be used if overlays have
+     changed in the buffer displayed by the window, so give up if they
+     have.  */
+  if (w->last_overlay_modified != OVERLAY_MODIFF)
+    GIVE_UP (21);
+
   /* Verify that narrowing has not changed.
      Also verify that we were not told to prevent redisplay optimizations.
      It would be nice to further
@@ -17719,7 +17764,7 @@ try_window_id (struct window *w)
        = run.current_y = run.desired_y = run.height = 0;
       first_unchanged_at_end_row = NULL;
     }
-  IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
+  IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
 
 
   /* Find the cursor if not already found.  We have to decide whether
@@ -17946,7 +17991,7 @@ try_window_id (struct window *w)
             the current matrix?  I don't think so, so we mark rows
             displayed invalid in the current matrix by setting their
             enabled_p flag to zero.  */
-         MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
+         SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
          if (display_line (&it))
            last_text_row_at_end = it.glyph_row - 1;
        }
@@ -18015,8 +18060,8 @@ try_window_id (struct window *w)
   else
     emacs_abort ();
 
-  IF_DEBUG (debug_end_pos = w->window_end_pos;
-           debug_end_vpos = w->window_end_vpos);
+  IF_DEBUG ((debug_end_pos = w->window_end_pos,
+            debug_end_vpos = w->window_end_vpos));
 
   /* Record that display has not been completed.  */
   w->window_end_valid = 0;
@@ -18804,10 +18849,14 @@ extend_face_to_end_of_line (struct it *it)
      1-``pixel'' wide, so they hit the equality too early.  This grace
      is needed only for R2L rows that are not continued, to produce
      one extra blank where we could display the cursor.  */
-  if (it->current_x >= it->last_visible_x
-      + (!FRAME_WINDOW_P (f)
-        && it->glyph_row->reversed_p
-        && !it->glyph_row->continued_p))
+  if ((it->current_x >= it->last_visible_x
+       + (!FRAME_WINDOW_P (f)
+         && it->glyph_row->reversed_p
+         && !it->glyph_row->continued_p))
+      /* If the window has display margins, we will need to extend
+        their face even if the text area is filled.  */
+      && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+          || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
     return;
 
   /* The default face, possibly remapped. */
@@ -18855,6 +18904,32 @@ extend_face_to_end_of_line (struct it *it)
          it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
          it->glyph_row->used[TEXT_AREA] = 1;
        }
+      /* Mode line and the header line don't have margins, and
+        likewise the frame's tool-bar window, if there is any.  */
+      if (!(it->glyph_row->mode_line_p
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
+           || (WINDOWP (f->tool_bar_window)
+               && it->w == XWINDOW (f->tool_bar_window))
+#endif
+           ))
+       {
+         if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+             && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
+           {
+             it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
+             it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
+               default_face->id;
+             it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
+           }
+         if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
+             && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
+           {
+             it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
+             it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
+               default_face->id;
+             it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
+           }
+       }
 #ifdef HAVE_WINDOW_SYSTEM
       if (it->glyph_row->reversed_p)
        {
@@ -18920,6 +18995,34 @@ extend_face_to_end_of_line (struct it *it)
       it->object = make_number (0);
       it->c = it->char_to_display = ' ';
       it->len = 1;
+
+      if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+         && (it->glyph_row->used[LEFT_MARGIN_AREA]
+             < WINDOW_LEFT_MARGIN_WIDTH (it->w))
+         && !it->glyph_row->mode_line_p
+         && default_face->background != FRAME_BACKGROUND_PIXEL (f))
+       {
+         struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
+         struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
+
+         for (it->current_x = 0; g < e; g++)
+           it->current_x += g->pixel_width;
+
+         it->area = LEFT_MARGIN_AREA;
+         it->face_id = default_face->id;
+         while (it->glyph_row->used[LEFT_MARGIN_AREA]
+                < WINDOW_LEFT_MARGIN_WIDTH (it->w))
+           {
+             PRODUCE_GLYPHS (it);
+             /* term.c:produce_glyphs advances it->current_x only for
+                TEXT_AREA.  */
+             it->current_x += it->pixel_width;
+           }
+
+         it->current_x = saved_x;
+         it->area = TEXT_AREA;
+       }
+
       /* The last row's blank glyphs should get the default face, to
         avoid painting the rest of the window with the region face,
         if the region ends at ZV.  */
@@ -18927,12 +19030,35 @@ extend_face_to_end_of_line (struct it *it)
        it->face_id = default_face->id;
       else
        it->face_id = face->id;
-
       PRODUCE_GLYPHS (it);
 
       while (it->current_x <= it->last_visible_x)
        PRODUCE_GLYPHS (it);
 
+      if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
+         && (it->glyph_row->used[RIGHT_MARGIN_AREA]
+             < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
+         && !it->glyph_row->mode_line_p
+         && default_face->background != FRAME_BACKGROUND_PIXEL (f))
+       {
+         struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
+         struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
+
+         for ( ; g < e; g++)
+           it->current_x += g->pixel_width;
+
+         it->area = RIGHT_MARGIN_AREA;
+         it->face_id = default_face->id;
+         while (it->glyph_row->used[RIGHT_MARGIN_AREA]
+                < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
+           {
+             PRODUCE_GLYPHS (it);
+             it->current_x += it->pixel_width;
+           }
+
+         it->area = TEXT_AREA;
+       }
+
       /* Don't count these blanks really.  It would let us insert a left
         truncation glyph below and make us set the cursor on them, maybe.  */
       it->current_x = saved_x;
@@ -19785,6 +19911,9 @@ display_line (struct it *it)
                        }
                      else if (it->bidi_p)
                        RECORD_MAX_MIN_POS (it);
+                     if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+                         || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+                       extend_face_to_end_of_line (it);
                    }
                  else if (CHAR_GLYPH_PADDING_P (*glyph)
                           && !FRAME_WINDOW_P (it->f))
@@ -19813,6 +19942,9 @@ display_line (struct it *it)
                      it->max_descent = descent;
                      it->max_phys_ascent = phys_ascent;
                      it->max_phys_descent = phys_descent;
+                     if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+                         || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+                       extend_face_to_end_of_line (it);
                    }
                  else if (wrap_row_used > 0)
                    {
@@ -19857,6 +19989,9 @@ display_line (struct it *it)
                      row->continued_p = 1;
                      glyph->pixel_width = it->last_visible_x - x;
                      it->starts_in_middle_of_char_p = 1;
+                     if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
+                         || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
+                       extend_face_to_end_of_line (it);
                    }
                  else
                    {
@@ -20268,6 +20403,7 @@ See also `bidi-paragraph-direction'.  */)
       itb.string.s = NULL;
       itb.string.lstring = Qnil;
       itb.string.bufpos = 0;
+      itb.string.from_disp_str = 0;
       itb.string.unibyte = 0;
       /* We have no window to use here for ignoring window-specific
         overlays.  Using NULL for window pointer will cause
@@ -20512,11 +20648,26 @@ Value is the new character position of point.  */)
         of this or previous line to make sure we are before point in
         the logical order (since the move_it_* functions can only
         move forward).  */
+    reseat:
       reseat_at_previous_visible_line_start (&it);
       it.current_x = it.hpos = it.current_y = it.vpos = 0;
       if (IT_CHARPOS (it) != PT)
-       move_it_to (&it, overshoot_expected ? PT - 1 : PT,
-                   -1, -1, -1, MOVE_TO_POS);
+       {
+         move_it_to (&it, overshoot_expected ? PT - 1 : PT,
+                     -1, -1, -1, MOVE_TO_POS);
+         /* If we missed point because the character there is
+            displayed out of a display vector that has more than one
+            glyph, retry expecting overshoot.  */
+         if (it.method == GET_FROM_DISPLAY_VECTOR
+             && it.current.dpvec_index > 0
+             && !overshoot_expected)
+           {
+             overshoot_expected = true;
+             goto reseat;
+           }
+         else if (IT_CHARPOS (it) != PT && !overshoot_expected)
+           move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
+       }
       pt_x = it.current_x;
       pt_vpos = it.vpos;
       if (dir > 0 || overshoot_expected)
@@ -20545,11 +20696,16 @@ Value is the new character position of point.  */)
       else if (pixel_width <= 0)
        pixel_width = 1;
 
-      /* If there's a display string at point, we are actually at the
-        glyph to the left of point, so we need to correct the X
-        coordinate.  */
+      /* If there's a display string (or something similar) at point,
+        we are actually at the glyph to the left of point, so we need
+        to correct the X coordinate.  */
       if (overshoot_expected)
-       pt_x += pixel_width;
+       {
+         if (it.bidi_p)
+           pt_x += pixel_width * it.bidi_it.scan_dir;
+         else
+           pt_x += pixel_width;
+       }
 
       /* Compute target X coordinate, either to the left or to the
         right of point.  On TTY frames, all characters have the same
@@ -20605,15 +20761,37 @@ Value is the new character position of point.  */)
         character at point.  */
       if (FRAME_WINDOW_P (it.f) && dir < 0)
        {
-         struct text_pos new_pos = it.current.pos;
+         struct text_pos new_pos;
          enum move_it_result rc = MOVE_X_REACHED;
 
+         if (it.current_x == 0)
+           get_next_display_element (&it);
+         if (it.what == IT_COMPOSITION)
+           {
+             new_pos.charpos = it.cmp_it.charpos;
+             new_pos.bytepos = -1;
+           }
+         else
+           new_pos = it.current.pos;
+
          while (it.current_x + it.pixel_width <= target_x
                 && rc == MOVE_X_REACHED)
            {
              int new_x = it.current_x + it.pixel_width;
 
-             new_pos = it.current.pos;
+             /* For composed characters, we want the position of the
+                first character in the grapheme cluster (usually, the
+                composition's base character), whereas it.current
+                might give us the position of the _last_ one, e.g. if
+                the composition is rendered in reverse due to bidi
+                reordering.  */
+             if (it.what == IT_COMPOSITION)
+               {
+                 new_pos.charpos = it.cmp_it.charpos;
+                 new_pos.bytepos = -1;
+               }
+             else
+               new_pos = it.current.pos;
              if (new_x == it.current_x)
                new_x++;
              rc = move_it_in_display_line_to (&it, ZV, new_x,
@@ -20621,21 +20799,10 @@ Value is the new character position of point.  */)
              if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
                break;
            }
-         /* If we ended up on a composed character inside
-            bidi-reordered text (e.g., Hebrew text with diacritics),
-            the iterator gives us the buffer position of the last (in
-            logical order) character of the composed grapheme cluster,
-            which is not what we want.  So we cheat: we compute the
-            character position of the character that follows (in the
-            logical order) the one where the above loop stopped.  That
-            character will appear on display to the left of point.  */
-         if (it.bidi_p
-             && it.bidi_it.scan_dir == -1
-             && new_pos.charpos - IT_CHARPOS (it) > 1)
-           {
-             new_pos.charpos = IT_CHARPOS (it) + 1;
-             new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
-           }
+         /* The previous position we saw in the loop is the one we
+            want.  */
+         if (new_pos.bytepos == -1)
+           new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
          it.current.pos = new_pos;
        }
       else
@@ -20727,8 +20894,7 @@ display_menu_bar (struct window *w)
   eassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
-  /* PXW: Use FRAME_PIXEL_WIDTH (f) here?  */
-  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+  it.last_visible_x = FRAME_PIXEL_WIDTH (f);
 #elif defined (HAVE_X_WINDOWS) /* X without toolkit.  */
   if (FRAME_WINDOW_P (f))
     {
@@ -20739,8 +20905,7 @@ display_menu_bar (struct window *w)
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
-      /* PXW: Use FRAME_PIXEL_WIDTH (f) here?  */
-      it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+      it.last_visible_x = FRAME_PIXEL_WIDTH (f);
     }
   else
 #endif /* not USE_X_TOOLKIT and not USE_GTK */
@@ -20763,7 +20928,7 @@ display_menu_bar (struct window *w)
     {
       struct glyph_row *row = it.glyph_row + i;
       clear_glyph_row (row);
-      row->enabled_p = 1;
+      row->enabled_p = true;
       row->full_width_p = 1;
     }
 
@@ -20873,7 +21038,7 @@ display_tty_menu_item (const char *item_text, int width, int face_id,
   row->full_width_p = 1;
   saved_reversed = row->reversed_p;
   row->reversed_p = 0;
-  row->enabled_p = 1;
+  row->enabled_p = true;
 
   /* Arrange for the menu item glyphs to start at (X,Y) and have the
      desired face.  */
@@ -21039,7 +21204,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
   init_iterator (&it, w, -1, -1, NULL, face_id);
   /* Don't extend on a previously drawn mode-line.
      This may happen if called from pos_visible_p.  */
-  it.glyph_row->enabled_p = 0;
+  it.glyph_row->enabled_p = false;
   prepare_desired_row (it.glyph_row);
 
   it.glyph_row->mode_line_p = 1;
@@ -23786,7 +23951,6 @@ set_glyph_string_background_width (struct glyph_string *s, int start, int last_x
      the drawing area, set S->extends_to_end_of_line_p.  */
 
   if (start == s->row->used[s->area]
-      && s->area == TEXT_AREA
       && ((s->row->fill_line_p
           && (s->hl == DRAW_NORMAL_TEXT
               || s->hl == DRAW_IMAGE_RAISED
@@ -27078,9 +27242,9 @@ clear_mouse_face (Mouse_HLInfo *hlinfo)
   return cleared;
 }
 
-/* Return non-zero if the coordinates HPOS and VPOS on windows W are
+/* Return true if the coordinates HPOS and VPOS on windows W are
    within the mouse face on that window.  */
-static int
+static bool
 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
 {
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
@@ -27088,48 +27252,48 @@ coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
   /* Quickly resolve the easy cases.  */
   if (!(WINDOWP (hlinfo->mouse_face_window)
        && XWINDOW (hlinfo->mouse_face_window) == w))
-    return 0;
+    return false;
   if (vpos < hlinfo->mouse_face_beg_row
       || vpos > hlinfo->mouse_face_end_row)
-    return 0;
+    return false;
   if (vpos > hlinfo->mouse_face_beg_row
       && vpos < hlinfo->mouse_face_end_row)
-    return 1;
+    return true;
 
   if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
     {
       if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
        {
          if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
-           return 1;
+           return true;
        }
       else if ((vpos == hlinfo->mouse_face_beg_row
                && hpos >= hlinfo->mouse_face_beg_col)
               || (vpos == hlinfo->mouse_face_end_row
                   && hpos < hlinfo->mouse_face_end_col))
-       return 1;
+       return true;
     }
   else
     {
        if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
        {
          if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
-           return 1;
+           return true;
        }
       else if ((vpos == hlinfo->mouse_face_beg_row
                && hpos <= hlinfo->mouse_face_beg_col)
               || (vpos == hlinfo->mouse_face_end_row
                   && hpos > hlinfo->mouse_face_end_col))
-       return 1;
+       return true;
     }
-  return 0;
+  return false;
 }
 
 
 /* EXPORT:
-   Non-zero if physical cursor of window W is within mouse face.  */
+   True if physical cursor of window W is within mouse face.  */
 
-int
+bool
 cursor_in_mouse_face_p (struct window *w)
 {
   int hpos = w->phys_cursor.hpos;
@@ -29113,7 +29277,8 @@ x_draw_right_divider (struct window *w)
       int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
       int x1 = WINDOW_RIGHT_EDGE_X (w);
       int y0 = WINDOW_TOP_EDGE_Y (w);
-      int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+      /* The bottom divider prevails.  */
+      int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
 
       FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
     }