Merge from emacs-24; up to 2014-06-02T14:17:07Z!michael.albinus@gmx.de
[bpt/emacs.git] / src / xdisp.c
index 33c99cd..54a8c8b 100644 (file)
@@ -1262,12 +1262,23 @@ Value is the height in pixels of the line at point.  */)
   struct it it;
   struct text_pos pt;
   struct window *w = XWINDOW (selected_window);
+  struct buffer *old_buffer = NULL;
+  Lisp_Object result;
 
+  if (XBUFFER (w->contents) != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal_1 (XBUFFER (w->contents));
+    }
   SET_TEXT_POS (pt, PT, PT_BYTE);
   start_display (&it, w, pt);
   it.vpos = it.current_y = 0;
   last_height = 0;
-  return make_number (line_bottom_y (&it));
+  result = make_number (line_bottom_y (&it));
+  if (old_buffer)
+    set_buffer_internal_1 (old_buffer);
+
+  return result;
 }
 
 /* Return the default pixel height of text lines in window W.  The
@@ -2580,8 +2591,8 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
    following.  Return the result, or nil if something went
    wrong.  Prevent redisplay during the evaluation.  */
 
-Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+static Lisp_Object
+safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
 {
   Lisp_Object val;
 
@@ -2589,21 +2600,20 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
     val = Qnil;
   else
     {
-      va_list ap;
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
       Lisp_Object *args = alloca (nargs * word_size);
 
       args[0] = func;
-      va_start (ap, func);
       for (i = 1; i < nargs; i++)
        args[i] = va_arg (ap, Lisp_Object);
-      va_end (ap);
 
       GCPRO1 (args[0]);
       gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
+      if (inhibit_quit)
+       specbind (Qinhibit_quit, Qt);
       /* Use Qt to ensure debugger does not run,
         so there is no possibility of wanting to redisplay.  */
       val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
@@ -2615,6 +2625,17 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
   return val;
 }
 
+Lisp_Object
+safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+{
+  Lisp_Object retval;
+  va_list ap;
+
+  va_start (ap, func);
+  retval = safe__call (false, nargs, func, ap);
+  va_end (ap);
+  return retval;
+}
 
 /* Call function FN with one argument ARG.
    Return the result, or nil if something went wrong.  */
@@ -2625,12 +2646,30 @@ safe_call1 (Lisp_Object fn, Lisp_Object arg)
   return safe_call (2, fn, arg);
 }
 
+static Lisp_Object
+safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
+{
+  Lisp_Object retval;
+  va_list ap;
+
+  va_start (ap, fn);
+  retval = safe__call (inhibit_quit, 2, fn, ap);
+  va_end (ap);
+  return retval;
+}
+
 static Lisp_Object Qeval;
 
 Lisp_Object
 safe_eval (Lisp_Object sexpr)
 {
-  return safe_call1 (Qeval, sexpr);
+  return safe__call1 (false, Qeval, sexpr);
+}
+
+static Lisp_Object
+safe__eval (bool inhibit_quit, Lisp_Object sexpr)
+{
+  return safe__call1 (inhibit_quit, Qeval, sexpr);
 }
 
 /* Call function FN with two arguments ARG1 and ARG2.
@@ -8517,7 +8556,7 @@ move_it_in_display_line_to (struct it *it,
        }
       else
        {
-         if (it->line_wrap == WORD_WRAP)
+         if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
            {
              if (IT_DISPLAYING_WHITESPACE (it))
                may_wrap = 1;
@@ -8651,7 +8690,12 @@ 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)))
+                         && 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)))
                    {
                      ++it->hpos;
                      it->current_x = new_x;
@@ -8796,8 +8840,11 @@ move_it_in_display_line_to (struct it *it,
                  if (closest_pos < ZV)
                    {
                      RESTORE_IT (it, &ppos_it, ppos_data);
-                     move_it_in_display_line_to (it, closest_pos, -1,
-                                                 MOVE_TO_POS);
+                     /* Don't recurse if closest_pos is equal to
+                        to_charpos, since we have just tried that.  */
+                     if (closest_pos != to_charpos)
+                       move_it_in_display_line_to (it, closest_pos, -1,
+                                                   MOVE_TO_POS);
                      result = MOVE_POS_MATCH_OR_ZV;
                    }
                  else
@@ -8858,8 +8905,9 @@ move_it_in_display_line_to (struct it *it,
                      && !at_eob_p && closest_pos < ZV)
                    {
                      RESTORE_IT (it, &ppos_it, ppos_data);
-                     move_it_in_display_line_to (it, closest_pos, -1,
-                                                 MOVE_TO_POS);
+                     if (closest_pos != to_charpos)
+                       move_it_in_display_line_to (it, closest_pos, -1,
+                                                   MOVE_TO_POS);
                    }
                  result = MOVE_POS_MATCH_OR_ZV;
                  break;
@@ -8877,7 +8925,9 @@ move_it_in_display_line_to (struct it *it,
              if (closest_pos < ZV)
                {
                  RESTORE_IT (it, &ppos_it, ppos_data);
-                 move_it_in_display_line_to (it, closest_pos, -1, MOVE_TO_POS);
+                 if (closest_pos != to_charpos)
+                   move_it_in_display_line_to (it, closest_pos, -1,
+                                               MOVE_TO_POS);
                }
              result = MOVE_POS_MATCH_OR_ZV;
              break;
@@ -9506,6 +9556,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
       ptrdiff_t start_charpos, i;
       int nchars_per_row
        = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
+      bool hit_pos_limit = false;
       ptrdiff_t pos_limit;
 
       /* Start at the beginning of the screen line containing IT's
@@ -9522,8 +9573,11 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
        pos_limit = BEGV;
       else
        pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
+
       for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
        back_to_previous_visible_line_start (it);
+      if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
+       hit_pos_limit = true;
       reseat (it, it->current.pos, 1);
 
       /* Move further back if we end up in a string or an image.  */
@@ -9567,6 +9621,25 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
          else
            bidi_unshelve_cache (it2data, 1);
        }
+      else if (hit_pos_limit && pos_limit > BEGV
+              && dvpos < 0 && it2.vpos < -dvpos)
+       {
+         /* If we hit the limit, but still didn't make it far enough
+            back, that means there's a display string with a newline
+            covering a large chunk of text, and that caused
+            back_to_previous_visible_line_start try to go too far.
+            Punish those who commit such atrocities by going back
+            until we've reached DVPOS, after lifting the limit, which
+            could make it slow for very long lines.  "If it hurts,
+            don't do that!"  */
+         dvpos += it2.vpos;
+         RESTORE_IT (it, it, it2data);
+         for (i = -dvpos; i > 0; --i)
+           {
+             back_to_previous_visible_line_start (it);
+             it->vpos--;
+           }
+       }
       else
        RESTORE_IT (it, it, it2data);
     }
@@ -9595,19 +9668,23 @@ character.  TO, if non-nil, specifies the last text position and
 defaults to the maximum accessible position of the buffer.  If TO is t,
 use the maximum accessible position that is not a newline character.
 
-The optional argument X_LIMIT, if non-nil, specifies the maximum text
-width that can be returned.  X_LIMIT nil or omitted, means to use the
+The optional argument X-LIMIT, if non-nil, specifies the maximum text
+width that can be returned.  X-LIMIT nil or omitted, means to use the
 pixel-width of WINDOW's body; use this if you do not intend to change
 the width of WINDOW.  Use the maximum width WINDOW may assume if you
-intend to change WINDOW's width.
+intend to change WINDOW's width.  In any case, text whose x-coordinate
+is beyond X-LIMIT is ignored.  Since calculating the width of long lines
+can take some time, it's always a good idea to make this argument as
+small as possible; in particular, if the buffer contains long lines that
+shall be truncated anyway.
 
-The optional argument Y_LIMIT, if non-nil, specifies the maximum text
+The optional argument Y-LIMIT, if non-nil, specifies the maximum text
 height that can be returned.  Text lines whose y-coordinate is beyond
-Y_LIMIT are ignored.  Since calculating the text height of a large
+Y-LIMIT are ignored.  Since calculating the text height of a large
 buffer can take some time, it makes sense to specify this argument if
 the size of the buffer is unknown.
 
-Optional argument MODE_AND_HEADER_LINE nil or omitted means do not
+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,
@@ -10124,19 +10201,17 @@ message_with_string (const char *m, Lisp_Object string, int log)
     {
       if (m)
        {
-         /* ENCODE_SYSTEM below can GC and/or relocate the Lisp
-            String whose data pointer might be passed to us in M.  So
-            we use a local copy.  */
-         char *fmt = xstrdup (m);
+         /* ENCODE_SYSTEM below can GC and/or relocate the
+            Lisp data, so make sure we don't use it here.  */
+         eassert (relocatable_string_data_p (m) != 1);
 
          if (noninteractive_need_newline)
            putc ('\n', stderr);
          noninteractive_need_newline = 0;
-         fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string)));
+         fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string)));
          if (!cursor_in_echo_area)
            fprintf (stderr, "\n");
          fflush (stderr);
-         xfree (fmt);
        }
     }
   else if (INTERACTIVE)
@@ -11500,7 +11575,7 @@ prepare_menu_bars (void)
                }
            }
        }
-      safe_call1 (Vpre_redisplay_function, windows);
+      safe__call1 (true, Vpre_redisplay_function, windows);
     }
 
   /* Update all frame titles based on their buffer names, etc.  We do
@@ -11731,11 +11806,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Tool-bar item index of the item on which a mouse button was pressed
-   or -1.  */
-
-int last_tool_bar_item;
-
 /* Select `frame' temporarily without running all the code in
    do_switch_frame.
    FIXME: Maybe do_switch_frame should be trimmed down similarly
@@ -12537,7 +12607,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
      where the button was pressed, disregarding where it was
      released.  */
   if (NILP (Vmouse_highlight) && !down_p)
-    prop_idx = last_tool_bar_item;
+    prop_idx = f->last_tool_bar_item;
 
   /* If item is disabled, do nothing.  */
   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
@@ -12549,7 +12619,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
       /* Show item in pressed state.  */
       if (!NILP (Vmouse_highlight))
        show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
-      last_tool_bar_item = prop_idx;
+      f->last_tool_bar_item = prop_idx;
     }
   else
     {
@@ -12574,7 +12644,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
       event.arg = key;
       event.modifiers = modifiers;
       kbd_buffer_store_event (&event);
-      last_tool_bar_item = -1;
+      f->last_tool_bar_item = -1;
     }
 }
 
@@ -12624,8 +12694,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
   mouse_down_p = (x_mouse_grabbed (dpyinfo)
                  && f == dpyinfo->last_mouse_frame);
 
-  if (mouse_down_p
-      && last_tool_bar_item != prop_idx)
+  if (mouse_down_p && f->last_tool_bar_item != prop_idx)
     return;
 
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
@@ -14344,7 +14413,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                              pos_after, 0);
 
                if (prop_pos >= pos_before)
-                 bpos_max = prop_pos - 1;
+                 bpos_max = prop_pos;
              }
            if (INTEGERP (chprop))
              {
@@ -14418,7 +14487,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                              pos_after, 0);
 
                if (prop_pos >= pos_before)
-                 bpos_max = prop_pos - 1;
+                 bpos_max = prop_pos;
              }
            if (INTEGERP (chprop))
              {
@@ -14448,7 +14517,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
      GLYPH_BEFORE and GLYPH_AFTER.  */
   if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
        && BUFFERP (glyph->object) && glyph->charpos == pt_old)
-      && !(bpos_max < pt_old && pt_old <= bpos_covered))
+      && !(bpos_max <= pt_old && pt_old <= bpos_covered))
     {
       /* An empty line has a single glyph whose OBJECT is zero and
         whose CHARPOS is the position of a newline on that line.
@@ -15635,9 +15704,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
   return rc;
 }
 
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
 void
 set_vertical_scroll_bar (struct window *w)
 {
@@ -16391,12 +16457,50 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* Consider the following case: Window starts at BEGV, there is
      invisible, intangible text at BEGV, so that display starts at
      some point START > BEGV.  It can happen that we are called with
-     PT somewhere between BEGV and START.  Try to handle that case.  */
+     PT somewhere between BEGV and START.  Try to handle that case,
+     and similar ones.  */
   if (w->cursor.vpos < 0)
     {
-      struct glyph_row *row = w->current_matrix->rows;
-      if (row->mode_line_p)
-       ++row;
+      /* First, try locating the proper glyph row for PT.  */
+      struct glyph_row *row =
+       row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0);
+
+      /* Sometimes point is at the beginning of invisible text that is
+        before the 1st character displayed in the row.  In that case,
+        row_containing_pos fails to find the row, because no glyphs
+        with appropriate buffer positions are present in the row.
+        Therefore, we next try to find the row which shows the 1st
+        position after the invisible text.  */
+      if (!row)
+       {
+         Lisp_Object val =
+           get_char_property_and_overlay (make_number (PT), Qinvisible,
+                                          Qnil, NULL);
+
+         if (TEXT_PROP_MEANS_INVISIBLE (val))
+           {
+             ptrdiff_t alt_pos;
+             Lisp_Object invis_end =
+               Fnext_single_char_property_change (make_number (PT), Qinvisible,
+                                                  Qnil, Qnil);
+
+             if (NATNUMP (invis_end))
+               alt_pos = XFASTINT (invis_end);
+             else
+               alt_pos = ZV;
+             row = row_containing_pos (w, alt_pos, w->current_matrix->rows,
+                                       NULL, 0);
+           }
+       }
+      /* Finally, fall back on the first row of the window after the
+        header line (if any).  This is slightly better than not
+        displaying the cursor at all.  */
+      if (!row)
+       {
+         row = w->current_matrix->rows;
+         if (row->mode_line_p)
+           ++row;
+       }
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
 
@@ -18607,6 +18711,7 @@ insert_left_trunc_glyphs (struct it *it)
   truncate_it.current_x = 0;
   truncate_it.face_id = DEFAULT_FACE_ID;
   truncate_it.glyph_row = &scratch_glyph_row;
+  truncate_it.area = TEXT_AREA;
   truncate_it.glyph_row->used[TEXT_AREA] = 0;
   CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
   truncate_it.object = make_number (0);
@@ -20857,6 +20962,30 @@ Value is the new character position of point.  */)
              move_it_by_lines (&it, -1);
              target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
              target_is_eol_p = true;
+             /* Under word-wrap, we don't know the x coordinate of
+                the last character displayed on the previous line,
+                which immediately precedes the wrap point.  To find
+                out its x coordinate, we try moving to the right
+                margin of the window, which will stop at the wrap
+                point, and then reset target_x to point at the
+                character that precedes the wrap point.  This is not
+                needed on GUI frames, because (see below) there we
+                move from the left margin one grapheme cluster at a
+                time, and stop when we hit the wrap point.  */
+             if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
+               {
+                 void *it_data = NULL;
+                 struct it it2;
+
+                 SAVE_IT (it2, it, it_data);
+                 move_it_in_display_line_to (&it, ZV, target_x,
+                                             MOVE_TO_POS | MOVE_TO_X);
+                 /* If we arrived at target_x, that _is_ the last
+                    character on the previous line.  */
+                 if (it.current_x != target_x)
+                   target_x = it.current_x - 1;
+                 RESTORE_IT (&it, &it2, it_data);
+               }
            }
        }
       else
@@ -20895,7 +21024,12 @@ Value is the new character position of point.  */)
            new_pos = it.current.pos;
 
          while (it.current_x + it.pixel_width <= target_x
-                && rc == MOVE_X_REACHED)
+                && (rc == MOVE_X_REACHED
+                    /* Under word-wrap, move_it_in_display_line_to
+                       stops at correct coordinates, but sometimes
+                       returns MOVE_POS_MATCH_OR_ZV.  */
+                    || (it.line_wrap == WORD_WRAP
+                        && rc == MOVE_POS_MATCH_OR_ZV)))
            {
              int new_x = it.current_x + it.pixel_width;
 
@@ -21746,7 +21880,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
            if (CONSP (XCDR (elt)))
              {
                Lisp_Object spec;
-               spec = safe_eval (XCAR (XCDR (elt)));
+               spec = safe__eval (true, XCAR (XCDR (elt)));
                n += display_mode_element (it, depth, field_width - n,
                                           precision - n, spec, props,
                                           risky);
@@ -22563,7 +22697,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
        return decode_mode_spec_buf;
     no_value:
         {
-         charp = decode_mode_spec_buf;
+         char *p = decode_mode_spec_buf;
          int pad = width - 2;
          while (pad-- > 0)
            *p++ = ' ';
@@ -23311,7 +23445,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
            return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
        }
 
-      prop = buffer_local_value_1 (prop, it->w->contents);
+      prop = buffer_local_value (prop, it->w->contents);
       if (EQ (prop, Qunbound))
        prop = Qnil;
     }
@@ -23363,7 +23497,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
              return OK_PIXELS (pixels);
            }
 
-         car = buffer_local_value_1 (car, it->w->contents);
+         car = buffer_local_value (car, it->w->contents);
          if (EQ (car, Qunbound))
            car = Qnil;
        }
@@ -23540,7 +23674,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
 #endif
     {
       eassert (face != NULL);
-      PREPARE_FACE_FOR_DISPLAY (f, face);
+      prepare_face_for_display (f, face);
     }
 
   return face;
@@ -23563,7 +23697,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 
   /* Make sure X resources of the face are allocated.  */
   eassert (face != NULL);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
+  prepare_face_for_display (f, face);
 
   if (two_byte_p)
     *two_byte_p = 0;
@@ -23880,7 +24014,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
   s->ybase += voffset;
 
   /* The case that face->gc == 0 is handled when drawing the glyph
-     string by calling PREPARE_FACE_FOR_DISPLAY.  */
+     string by calling prepare_face_for_display.  */
   eassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
@@ -24478,13 +24612,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
+         if (hl != overlap_hl)
+           clip_head = head;
          j = i;
          BUILD_GLYPH_STRINGS (j, start, h, t,
                               overlap_hl, dummy_x, last_x);
          start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
-         clip_head = head;
+         if (clip_head == NULL)
+           clip_head = head;
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -24505,7 +24642,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
-         clip_head = head;
+         if (hl == overlap_hl || clip_head == NULL)
+           clip_head = head;
          BUILD_GLYPH_STRINGS (i, start, h, t,
                               overlap_hl, dummy_x, last_x);
          for (s = h; s; s = s->next)
@@ -24529,13 +24667,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
+         if (hl != overlap_hl)
+           clip_tail = tail;
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
          /* Because BUILD_GLYPH_STRINGS updates the first argument,
             we don't have `end = i;' here.  */
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
-         clip_tail = tail;
+         if (clip_tail == NULL)
+           clip_tail = tail;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -24553,7 +24694,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
-         clip_tail = tail;
+         if (hl == overlap_hl || clip_tail == NULL)
+           clip_tail = tail;
          i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
@@ -24821,7 +24963,7 @@ produce_image_glyph (struct it *it)
   face = FACE_FROM_ID (it->f, it->face_id);
   eassert (face);
   /* Make sure X resources of the face is loaded.  */
-  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+  prepare_face_for_display (it->f, face);
 
   if (it->image_id < 0)
     {
@@ -25099,7 +25241,7 @@ produce_stretch_glyph (struct it *it)
     {
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
-      PREPARE_FACE_FOR_DISPLAY (it->f, face);
+      prepare_face_for_display (it->f, face);
     }
 #endif
 
@@ -25563,7 +25705,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
 
       face = FACE_FROM_ID (it->f, face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
-      PREPARE_FACE_FOR_DISPLAY (it->f, face);
+      prepare_face_for_display (it->f, face);
 
       if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
        {
@@ -26904,9 +27046,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
 
 /* Erase the image of a cursor of window W from the screen.  */
 
-#ifndef HAVE_NTGUI
-static
-#endif
 void
 erase_phys_cursor (struct window *w)
 {
@@ -27215,7 +27354,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
   if (/* If window is in the process of being destroyed, don't bother
         to do anything.  */
       w->current_matrix != NULL
-      /* Don't update mouse highlight if hidden */
+      /* Don't update mouse highlight if hidden */
       && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
       /* Recognize when we are called to operate on rows that don't exist
         anymore.  This can happen when a window is split.  */
@@ -28432,8 +28571,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
          else if (area == ON_MODE_LINE)
            {
              Lisp_Object default_help
-               = buffer_local_value_1 (Qmode_line_default_help_echo,
-                                       w->contents);
+               = buffer_local_value (Qmode_line_default_help_echo,
+                                     w->contents);
 
              if (STRINGP (default_help))
                {
@@ -28449,6 +28588,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
       /* Change the mouse pointer according to what is under it.  */
       if (FRAME_WINDOW_P (f))
        {
+         bool draggable = (! WINDOW_BOTTOMMOST_P (w)
+                           || minibuf_level
+                           || NILP (Vresize_mini_windows));
+
          dpyinfo = FRAME_DISPLAY_INFO (f);
          if (STRINGP (string))
            {
@@ -28465,11 +28608,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
                  map = Fget_text_property (pos, Qlocal_map, string);
                  if (!KEYMAPP (map))
                    map = Fget_text_property (pos, Qkeymap, string);
-                 if (!KEYMAPP (map))
+                 if (!KEYMAPP (map) && draggable)
                    cursor = dpyinfo->vertical_scroll_bar_cursor;
                }
            }
-         else
+         else if (draggable)
            /* Default mode-line pointer.  */
            cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
        }