]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Cleanup tooltips
[gnu-emacs] / src / xdisp.c
index d589080ac4c25fa38625f514b517bf21b1c673ef..b8dcdcec41fef15de01a0ab2c66f3fbd30dc2c93 100644 (file)
@@ -1321,6 +1321,11 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
   if (CHARPOS (top) > ZV)
     SET_TEXT_POS (top, BEGV, BEGV_BYTE);
 
   if (CHARPOS (top) > ZV)
     SET_TEXT_POS (top, BEGV, BEGV_BYTE);
 
+  /* If the top of the window is after CHARPOS, the latter is surely
+     not visible.  */
+  if (charpos >= 0 && CHARPOS (top) > charpos)
+    return visible_p;
+
   /* Compute exact mode line heights.  */
   if (WINDOW_WANTS_MODELINE_P (w))
     w->mode_line_height
   /* Compute exact mode line heights.  */
   if (WINDOW_WANTS_MODELINE_P (w))
     w->mode_line_height
@@ -1813,7 +1818,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
         cache and mode line face are not yet initialized.  */
       if (FRAME_FACE_CACHE (f))
        {
         cache and mode line face are not yet initialized.  */
       if (FRAME_FACE_CACHE (f))
        {
-         struct face *face = FACE_OPT_FROM_ID (f, face_id);
+         struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
          if (face)
            {
              if (face->font)
          if (face)
            {
              if (face->font)
@@ -2836,11 +2841,7 @@ init_iterator (struct it *it, struct window *w,
      frames when the fringes are turned off.  But leave the dimensions
      zero for tooltip frames, as these glyphs look ugly there and also
      sabotage calculations of tooltip dimensions in x-show-tip.  */
      frames when the fringes are turned off.  But leave the dimensions
      zero for tooltip frames, as these glyphs look ugly there and also
      sabotage calculations of tooltip dimensions in x-show-tip.  */
-#ifdef HAVE_WINDOW_SYSTEM
-  if (!(FRAME_WINDOW_P (it->f)
-       && FRAMEP (tip_frame)
-       && it->f == XFRAME (tip_frame)))
-#endif
+  if (!FRAME_TOOLTIP_P (it->f))
     {
       if (it->line_wrap == TRUNCATE)
        {
     {
       if (it->line_wrap == TRUNCATE)
        {
@@ -2918,7 +2919,7 @@ init_iterator (struct it *it, struct window *w,
 
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
 
       /* If we have a boxed mode line, make the first character appear
         with a left box line.  */
-      face = FACE_OPT_FROM_ID (it->f, remapped_base_face_id);
+      face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
       if (face && face->box != FACE_NO_BOX)
        it->start_of_box_run_p = true;
     }
       if (face && face->box != FACE_NO_BOX)
        it->start_of_box_run_p = true;
     }
@@ -3877,9 +3878,9 @@ handle_face_prop (struct it *it)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
          /* If it->face_id is -1, old_face below will be NULL, see
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
          /* If it->face_id is -1, old_face below will be NULL, see
-            the definition of FACE_OPT_FROM_ID.  This will happen if this
-            is the initial call that gets the face.  */
-         struct face *old_face = FACE_OPT_FROM_ID (it->f, it->face_id);
+            the definition of FACE_FROM_ID_OR_NULL.  This will happen
+            if this is the initial call that gets the face.  */
+         struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
 
          /* If the value of face_id of the iterator is -1, we have to
             look in front of IT's position and see whether there is a
 
          /* If the value of face_id of the iterator is -1, we have to
             look in front of IT's position and see whether there is a
@@ -3888,7 +3889,7 @@ handle_face_prop (struct it *it)
            {
              int prev_face_id = face_before_it_pos (it);
 
            {
              int prev_face_id = face_before_it_pos (it);
 
-             old_face = FACE_OPT_FROM_ID (it->f, prev_face_id);
+             old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
            }
 
          /* If the new face has a box, but the old face does not,
            }
 
          /* If the new face has a box, but the old face does not,
@@ -3988,7 +3989,7 @@ handle_face_prop (struct it *it)
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
       if (new_face_id != it->face_id)
        {
          struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
-         struct face *old_face = FACE_OPT_FROM_ID (it->f, it->face_id);
+         struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
 
          /* If new face has a box but old face hasn't, this is the
             start of a run of characters with box, i.e. it has a
 
          /* If new face has a box but old face hasn't, this is the
             start of a run of characters with box, i.e. it has a
@@ -5017,8 +5018,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
-      int fringe_bitmap;
-
       if (it)
        {
          if (!FRAME_WINDOW_P (it->f))
       if (it)
        {
          if (!FRAME_WINDOW_P (it->f))
@@ -5043,8 +5042,8 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 
 #ifdef HAVE_WINDOW_SYSTEM
       value = XCAR (XCDR (spec));
 
 #ifdef HAVE_WINDOW_SYSTEM
       value = XCAR (XCDR (spec));
-      if (!SYMBOLP (value)
-         || !(fringe_bitmap = lookup_fringe_bitmap (value)))
+      int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
+      if (! fringe_bitmap)
        /* If we return here, POSITION has been advanced
           across the text with this property.  */
        {
        /* If we return here, POSITION has been advanced
           across the text with this property.  */
        {
@@ -6097,7 +6096,7 @@ pop_it (struct it *it)
       break;
     case GET_FROM_STRING:
       {
       break;
     case GET_FROM_STRING:
       {
-       struct face *face = FACE_OPT_FROM_ID (it->f, it->face_id);
+       struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
 
        /* Restore the face_box_p flag, since it could have been
           overwritten by the face of the object that we just finished
 
        /* Restore the face_box_p flag, since it could have been
           overwritten by the face of the object that we just finished
@@ -6778,7 +6777,8 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
    || ((IT)->cmp_it.stop_pos == (CHARPOS)                              \
        && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS,      \
                                 END_CHARPOS, (IT)->w,                  \
    || ((IT)->cmp_it.stop_pos == (CHARPOS)                              \
        && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS,      \
                                 END_CHARPOS, (IT)->w,                  \
-                                FACE_OPT_FROM_ID ((IT)->f, (IT)->face_id),     \
+                                FACE_FROM_ID_OR_NULL ((IT)->f,         \
+                                                      (IT)->face_id),  \
                                 (IT)->string)))
 
 
                                 (IT)->string)))
 
 
@@ -7207,7 +7207,7 @@ get_next_display_element (struct it *it)
       if (it->method == GET_FROM_STRING && it->sp)
        {
          int face_id = underlying_face_id (it);
       if (it->method == GET_FROM_STRING && it->sp)
        {
          int face_id = underlying_face_id (it);
-         struct face *face = FACE_OPT_FROM_ID (it->f, face_id);
+         struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
 
          if (face)
            {
 
          if (face)
            {
@@ -7740,8 +7740,8 @@ next_element_from_display_vector (struct it *it)
       /* Glyphs in the display vector could have the box face, so we
         need to set the related flags in the iterator, as
         appropriate.  */
       /* Glyphs in the display vector could have the box face, so we
         need to set the related flags in the iterator, as
         appropriate.  */
-      this_face = FACE_OPT_FROM_ID (it->f, it->face_id);
-      prev_face = FACE_OPT_FROM_ID (it->f, prev_face_id);
+      this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
+      prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
 
       /* Is this character the first character of a box-face run?  */
       it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
 
       /* Is this character the first character of a box-face run?  */
       it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
@@ -7766,7 +7766,7 @@ next_element_from_display_vector (struct it *it)
                                            it->saved_face_id);
            }
        }
                                            it->saved_face_id);
            }
        }
-      next_face = FACE_OPT_FROM_ID (it->f, next_face_id);
+      next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
       it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
                              && (!next_face
                                  || next_face->box == FACE_NO_BOX));
       it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
                              && (!next_face
                                  || next_face->box == FACE_NO_BOX));
@@ -8610,8 +8610,7 @@ move_it_in_display_line_to (struct it *it,
           && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
 
   /* If there's a line-/wrap-prefix, handle it.  */
           && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
 
   /* If there's a line-/wrap-prefix, handle it.  */
-  if (it->hpos == 0 && it->method == GET_FROM_BUFFER
-      && it->current_y < it->last_visible_y)
+  if (it->hpos == 0 && it->method == GET_FROM_BUFFER)
     handle_line_prefix (it);
 
   if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
     handle_line_prefix (it);
 
   if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
@@ -9038,6 +9037,11 @@ move_it_in_display_line_to (struct it *it,
            }
          else
            result = MOVE_NEWLINE_OR_CR;
            }
          else
            result = MOVE_NEWLINE_OR_CR;
+         /* If we've processed the newline, make sure this flag is
+            reset, as it must only be set when the newline itself is
+            processed.  */
+         if (result == MOVE_NEWLINE_OR_CR)
+           it->constrain_row_ascent_descent_p = false;
          break;
        }
 
          break;
        }
 
@@ -9976,18 +9980,21 @@ include the height of both, if present, in the return value.  */)
       it.last_visible_x = max_x;
       /* 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,
       it.last_visible_x = max_x;
       /* 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.  Also bound width
-        value by X-LIMIT.  */
-      x = min (move_it_to (&it, end, INT_MAX, max_y, -1,
-                          MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y),
-              max_x);
+        we set it to INT_MAX and specify MOVE_TO_X.  */
+      x = move_it_to (&it, end, INT_MAX, max_y, -1,
+                     MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+      /* Don't return more than X-LIMIT.  */
+      if (x > max_x)
+        x = max_x;
     }
 
   /* Subtract height of header-line which was counted automatically by
      start_display.  */
     }
 
   /* Subtract height of header-line which was counted automatically by
      start_display.  */
-  y = min (it.current_y + it.max_ascent + it.max_descent
-          - WINDOW_HEADER_LINE_HEIGHT (w),
-          max_y);
+  y = it.current_y + it.max_ascent + it.max_descent
+    - WINDOW_HEADER_LINE_HEIGHT (w);
+  /* Don't return more than Y-LIMIT.  */
+  if (y > max_y)
+    y = max_y;
 
   if (EQ (mode_and_header_line, Qheader_line)
       || EQ (mode_and_header_line, Qt))
 
   if (EQ (mode_and_header_line, Qheader_line)
       || EQ (mode_and_header_line, Qt))
@@ -11702,7 +11709,7 @@ x_consider_frame_title (Lisp_Object frame)
   if ((FRAME_WINDOW_P (f)
        || FRAME_MINIBUF_ONLY_P (f)
        || f->explicit_name)
   if ((FRAME_WINDOW_P (f)
        || FRAME_MINIBUF_ONLY_P (f)
        || f->explicit_name)
-      && NILP (Fframe_parameter (frame, Qtooltip)))
+      && !FRAME_TOOLTIP_P (f))
     {
       /* Do we have more than one visible frame on this X display?  */
       Lisp_Object tail, other_frame, fmt;
     {
       /* Do we have more than one visible frame on this X display?  */
       Lisp_Object tail, other_frame, fmt;
@@ -11719,7 +11726,7 @@ x_consider_frame_title (Lisp_Object frame)
          if (tf != f
              && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
              && !FRAME_MINIBUF_ONLY_P (tf)
          if (tf != f
              && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
              && !FRAME_MINIBUF_ONLY_P (tf)
-             && !EQ (other_frame, tip_frame)
+             && !FRAME_TOOLTIP_P (tf)
              && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
            break;
        }
              && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
            break;
        }
@@ -11782,13 +11789,6 @@ prepare_menu_bars (void)
 {
   bool all_windows = windows_or_buffers_changed || update_mode_lines;
   bool some_windows = REDISPLAY_SOME_P ();
 {
   bool all_windows = windows_or_buffers_changed || update_mode_lines;
   bool some_windows = REDISPLAY_SOME_P ();
-  Lisp_Object tooltip_frame;
-
-#ifdef HAVE_WINDOW_SYSTEM
-  tooltip_frame = tip_frame;
-#else
-  tooltip_frame = Qnil;
-#endif
 
   if (FUNCTIONP (Vpre_redisplay_function))
     {
 
   if (FUNCTIONP (Vpre_redisplay_function))
     {
@@ -11829,7 +11829,7 @@ prepare_menu_bars (void)
              && !XBUFFER (w->contents)->text->redisplay)
            continue;
 
              && !XBUFFER (w->contents)->text->redisplay)
            continue;
 
-         if (!EQ (frame, tooltip_frame)
+         if (!FRAME_TOOLTIP_P (f)
              && (FRAME_ICONIFIED_P (f)
                  || FRAME_VISIBLE_P (f) == 1
                  /* Exclude TTY frames that are obscured because they
              && (FRAME_ICONIFIED_P (f)
                  || FRAME_VISIBLE_P (f) == 1
                  /* Exclude TTY frames that are obscured because they
@@ -11866,7 +11866,7 @@ prepare_menu_bars (void)
          struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
 
          /* Ignore tooltip frame.  */
          struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
 
          /* Ignore tooltip frame.  */
-         if (EQ (frame, tooltip_frame))
+         if (FRAME_TOOLTIP_P (f))
            continue;
 
          if (some_windows
            continue;
 
          if (some_windows
@@ -15506,12 +15506,14 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
 
    The new window start will be computed, based on W's width, starting
    from the start of the continued line.  It is the start of the
 
    The new window start will be computed, based on W's width, starting
    from the start of the continued line.  It is the start of the
-   screen line with the minimum distance from the old start W->start.  */
+   screen line with the minimum distance from the old start W->start,
+   which is still before point (otherwise point will definitely not
+   be visible in the window).  */
 
 static bool
 compute_window_start_on_continuation_line (struct window *w)
 {
 
 static bool
 compute_window_start_on_continuation_line (struct window *w)
 {
-  struct text_pos pos, start_pos;
+  struct text_pos pos, start_pos, pos_before_pt;
   bool window_start_changed_p = false;
 
   SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
   bool window_start_changed_p = false;
 
   SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
@@ -15539,10 +15541,14 @@ compute_window_start_on_continuation_line (struct window *w)
       reseat_at_previous_visible_line_start (&it);
 
       /* If the line start is "too far" away from the window start,
       reseat_at_previous_visible_line_start (&it);
 
       /* If the line start is "too far" away from the window start,
-         say it takes too much time to compute a new window start.  */
-      if (CHARPOS (start_pos) - IT_CHARPOS (it)
-         /* PXW: Do we need upper bounds here?  */
-         < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
+         say it takes too much time to compute a new window start.
+         Also, give up if the line start is after point, as in that
+         case point will not be visible with any window start we
+         compute.  */
+      if (IT_CHARPOS (it) <= PT
+         || (CHARPOS (start_pos) - IT_CHARPOS (it)
+             /* PXW: Do we need upper bounds here?  */
+             < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
        {
          int min_distance, distance;
 
        {
          int min_distance, distance;
 
@@ -15552,12 +15558,14 @@ compute_window_start_on_continuation_line (struct window *w)
             decreased, the new window start will be < the old start.
             So, we're looking for the display line start with the
             minimum distance from the old window start.  */
             decreased, the new window start will be < the old start.
             So, we're looking for the display line start with the
             minimum distance from the old window start.  */
-         pos = it.current.pos;
+         pos_before_pt = pos = it.current.pos;
          min_distance = INFINITY;
          while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
                 distance < min_distance)
            {
              min_distance = distance;
          min_distance = INFINITY;
          while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
                 distance < min_distance)
            {
              min_distance = distance;
+             if (CHARPOS (pos) <= PT)
+               pos_before_pt = pos;
              pos = it.current.pos;
              if (it.line_wrap == WORD_WRAP)
                {
              pos = it.current.pos;
              if (it.line_wrap == WORD_WRAP)
                {
@@ -15580,6 +15588,13 @@ compute_window_start_on_continuation_line (struct window *w)
                move_it_by_lines (&it, 1);
            }
 
                move_it_by_lines (&it, 1);
            }
 
+         /* It makes very little sense to make the new window start
+            after point, as point won't be visible.  If that's what
+            the loop above finds, fall back on the candidate before
+            or at point that is closest to the old window start.  */
+         if (CHARPOS (pos) > PT)
+           pos = pos_before_pt;
+
          /* Set the window start there.  */
          SET_MARKER_FROM_TEXT_POS (w->start, pos);
          window_start_changed_p = true;
          /* Set the window start there.  */
          SET_MARKER_FROM_TEXT_POS (w->start, pos);
          window_start_changed_p = true;
@@ -19509,7 +19524,6 @@ append_space_for_newline (struct it *it, bool default_face_p)
          struct text_pos saved_pos;
          Lisp_Object saved_object;
          struct face *face;
          struct text_pos saved_pos;
          Lisp_Object saved_object;
          struct face *face;
-         struct glyph *g;
 
          saved_object = it->object;
          saved_pos = it->position;
 
          saved_object = it->object;
          saved_pos = it->position;
@@ -19545,7 +19559,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
          /* Make sure this space glyph has the right ascent and
             descent values, or else cursor at end of line will look
             funny, and height of empty lines will be incorrect.  */
          /* Make sure this space glyph has the right ascent and
             descent values, or else cursor at end of line will look
             funny, and height of empty lines will be incorrect.  */
-         g = it->glyph_row->glyphs[TEXT_AREA] + n;
+         struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
          struct font *font = face->font ? face->font : FRAME_FONT (it->f);
          if (n == 0)
            {
          struct font *font = face->font ? face->font : FRAME_FONT (it->f);
          if (n == 0)
            {
@@ -19670,14 +19684,15 @@ extend_face_to_end_of_line (struct it *it)
     return;
 
   /* The default face, possibly remapped. */
     return;
 
   /* The default face, possibly remapped. */
-  default_face = FACE_OPT_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
+  default_face = FACE_FROM_ID_OR_NULL (f,
+                                      lookup_basic_face (f, DEFAULT_FACE_ID));
 
   /* Face extension extends the background and box of IT->face_id
      to the end of the line.  If the background equals the background
      of the frame, we don't have to do anything.  */
 
   /* Face extension extends the background and box of IT->face_id
      to the end of the line.  If the background equals the background
      of the frame, we don't have to do anything.  */
-  face = FACE_OPT_FROM_ID (f, (it->face_before_selective_p
-                              ? it->saved_face_id
-                              : it->face_id));
+  face = FACE_FROM_ID (f, (it->face_before_selective_p
+                          ? it->saved_face_id
+                          : it->face_id));
 
   if (FRAME_WINDOW_P (f)
       && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
 
   if (FRAME_WINDOW_P (f)
       && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
@@ -21843,7 +21858,6 @@ Value is the new character position of point.  */)
        }
 
       /* Move to the target X coordinate.  */
        }
 
       /* Move to the target X coordinate.  */
-#ifdef HAVE_WINDOW_SYSTEM
       /* On GUI frames, as we don't know the X coordinate of the
         character to the left of point, moving point to the left
         requires walking, one grapheme cluster at a time, until we
       /* On GUI frames, as we don't know the X coordinate of the
         character to the left of point, moving point to the left
         requires walking, one grapheme cluster at a time, until we
@@ -21900,9 +21914,7 @@ Value is the new character position of point.  */)
            new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
          it.current.pos = new_pos;
        }
            new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
          it.current.pos = new_pos;
        }
-      else
-#endif
-      if (it.current_x != target_x)
+      else if (it.current_x != target_x)
        move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
 
       /* If we ended up in a display string that covers point, move to
        move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
 
       /* If we ended up in a display string that covers point, move to
@@ -24782,7 +24794,7 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id,
   s->cmp_id = glyph->u.cmp.id;
   s->cmp_from = glyph->slice.cmp.from;
   s->cmp_to = glyph->slice.cmp.to + 1;
   s->cmp_id = glyph->u.cmp.id;
   s->cmp_from = glyph->slice.cmp.from;
   s->cmp_to = glyph->slice.cmp.to + 1;
-  s->face = FACE_OPT_FROM_ID (s->f, face_id);
+  s->face = FACE_FROM_ID (s->f, face_id);
   lgstring = composition_gstring_from_id (s->cmp_id);
   s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
   glyph++;
   lgstring = composition_gstring_from_id (s->cmp_id);
   s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
   glyph++;
@@ -25375,7 +25387,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
   do {                                                                     \
     int face_id = (row)->glyphs[area][START].face_id;                      \
 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
   do {                                                                     \
     int face_id = (row)->glyphs[area][START].face_id;                      \
-    struct face *base_face = FACE_OPT_FROM_ID (f, face_id);                \
+    struct face *base_face = FACE_FROM_ID (f, face_id);                    \
     ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id;                \
     struct composition *cmp = composition_table[cmp_id];                   \
     XChar2b *char2b;                                                       \
     ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id;                \
     struct composition *cmp = composition_table[cmp_id];                   \
     XChar2b *char2b;                                                       \
@@ -26692,12 +26704,8 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
       struct face *face;
 
       face_id = lookup_named_face (it->f, face_name, false);
       struct face *face;
 
       face_id = lookup_named_face (it->f, face_name, false);
-      if (face_id < 0)
-       return make_number (-1);
-
-      face = FACE_FROM_ID (it->f, face_id);
-      font = face->font;
-      if (font == NULL)
+      face = FACE_FROM_ID_OR_NULL (it->f, face_id);
+      if (face == NULL || ((font = face->font) == NULL))
        return make_number (-1);
       boff = font->baseline_offset;
       if (font->vertical_centering)
        return make_number (-1);
       boff = font->baseline_offset;
       if (font->vertical_centering)
@@ -27350,8 +27358,8 @@ x_produce_glyphs (struct it *it)
 
          eassume (0 < glyph_len); /* See Bug#8512.  */
          do
 
          eassume (0 < glyph_len); /* See Bug#8512.  */
          do
-           c = COMPOSITION_GLYPH (cmp, --glyph_len);
-         while (c == '\t' && 0 < glyph_len);
+           c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
+         while (c == '\t' && 0 < --glyph_len);
 
          bool right_padded = glyph_len < cmp->glyph_len;
          for (i = 0; i < glyph_len; i++)
 
          bool right_padded = glyph_len < cmp->glyph_len;
          for (i = 0; i < glyph_len; i++)
@@ -28681,12 +28689,12 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
            }
        }
 
            }
        }
 
-#ifdef HAVE_WINDOW_SYSTEM
       /* When we've written over the cursor, arrange for it to
         be displayed again.  */
       if (FRAME_WINDOW_P (f)
          && phys_cursor_on_p && !w->phys_cursor_on_p)
        {
       /* When we've written over the cursor, arrange for it to
         be displayed again.  */
       if (FRAME_WINDOW_P (f)
          && phys_cursor_on_p && !w->phys_cursor_on_p)
        {
+#ifdef HAVE_WINDOW_SYSTEM
          int hpos = w->phys_cursor.hpos;
 
          /* When the window is hscrolled, cursor hpos can legitimately be
          int hpos = w->phys_cursor.hpos;
 
          /* When the window is hscrolled, cursor hpos can legitimately be
@@ -28701,8 +28709,8 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
          display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
                                  w->phys_cursor.x, w->phys_cursor.y);
          unblock_input ();
          display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
                                  w->phys_cursor.x, w->phys_cursor.y);
          unblock_input ();
-       }
 #endif /* HAVE_WINDOW_SYSTEM */
 #endif /* HAVE_WINDOW_SYSTEM */
+       }
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -29642,12 +29650,17 @@ Returns the alist element for the first matching AREA in MAP.  */)
                        clip_to_bounds (INT_MIN, XINT (x), INT_MAX),
                        clip_to_bounds (INT_MIN, XINT (y), INT_MAX));
 }
                        clip_to_bounds (INT_MIN, XINT (x), INT_MAX),
                        clip_to_bounds (INT_MIN, XINT (y), INT_MAX));
 }
+#endif /* HAVE_WINDOW_SYSTEM */
 
 
 /* Display frame CURSOR, optionally using shape defined by POINTER.  */
 static void
 define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
 {
 
 
 /* Display frame CURSOR, optionally using shape defined by POINTER.  */
 static void
 define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
 {
+#ifdef HAVE_WINDOW_SYSTEM
+  if (!FRAME_WINDOW_P (f))
+    return;
+
   /* Do not change cursor shape while dragging mouse.  */
   if (EQ (do_mouse_tracking, Qdragging))
     return;
   /* Do not change cursor shape while dragging mouse.  */
   if (EQ (do_mouse_tracking, Qdragging))
     return;
@@ -29664,10 +29677,10 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
        cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
       else if (EQ (pointer, intern ("nhdrag")))
        cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
        cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
       else if (EQ (pointer, intern ("nhdrag")))
        cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
-#ifdef HAVE_X_WINDOWS
+# ifdef HAVE_X_WINDOWS
       else if (EQ (pointer, intern ("vdrag")))
        cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
       else if (EQ (pointer, intern ("vdrag")))
        cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
-#endif
+# endif
       else if (EQ (pointer, intern ("hourglass")))
        cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
       else if (EQ (pointer, Qmodeline))
       else if (EQ (pointer, intern ("hourglass")))
        cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
       else if (EQ (pointer, Qmodeline))
@@ -29678,10 +29691,9 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
 
   if (cursor != No_Cursor)
     FRAME_RIF (f)->define_frame_cursor (f, cursor);
 
   if (cursor != No_Cursor)
     FRAME_RIF (f)->define_frame_cursor (f, cursor);
+#endif
 }
 
 }
 
-#endif /* HAVE_WINDOW_SYSTEM */
-
 /* Take proper action when mouse has moved to the mode or header line
    or marginal area AREA of window W, x-position X and y-position Y.
    X is relative to the start of the text display area of W, so the
 /* Take proper action when mouse has moved to the mode or header line
    or marginal area AREA of window W, x-position X and y-position Y.
    X is relative to the start of the text display area of W, so the
@@ -29995,10 +30007,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
   if ((area == ON_MODE_LINE || area == ON_HEADER_LINE) && !mouse_face_shown)
     clear_mouse_face (hlinfo);
 
   if ((area == ON_MODE_LINE || area == ON_HEADER_LINE) && !mouse_face_shown)
     clear_mouse_face (hlinfo);
 
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (f))
-    define_frame_cursor1 (f, cursor, pointer);
-#endif
+  define_frame_cursor1 (f, cursor, pointer);
 }
 
 
 }
 
 
@@ -30203,15 +30212,15 @@ note_mouse_highlight (struct frame *f, int x, int y)
        {
          if (clear_mouse_face (hlinfo))
            cursor = No_Cursor;
        {
          if (clear_mouse_face (hlinfo))
            cursor = No_Cursor;
-#ifdef HAVE_WINDOW_SYSTEM
          if (FRAME_WINDOW_P (f) && NILP (pointer))
            {
          if (FRAME_WINDOW_P (f) && NILP (pointer))
            {
+#ifdef HAVE_WINDOW_SYSTEM
              if (area != TEXT_AREA)
                cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
              else
                pointer = Vvoid_text_area_pointer;
              if (area != TEXT_AREA)
                cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
              else
                pointer = Vvoid_text_area_pointer;
-           }
 #endif
 #endif
+           }
          goto set_cursor;
        }
 
          goto set_cursor;
        }
 
@@ -30523,15 +30532,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
     }
 
  set_cursor:
     }
 
  set_cursor:
-
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (f))
-    define_frame_cursor1 (f, cursor, pointer);
-#else
-  /* This is here to prevent a compiler error, about "label at end of
-     compound statement".  */
-  return;
-#endif
+  define_frame_cursor1 (f, cursor, pointer);
 }
 
 
 }