]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Cleanup tooltips
[gnu-emacs] / src / xdisp.c
index d0ff95257cefa2263a6944591779676d1253e499..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 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
@@ -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))
        {
-         struct face *face = FACE_FROM_ID (f, face_id);
+         struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
          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.  */
-#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)
        {
@@ -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.  */
-      face = FACE_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;
     }
@@ -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
-            the definition of FACE_FROM_ID.  This will happen if this
-            is the initial call that gets the face.  */
-         struct face *old_face = FACE_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
@@ -3888,7 +3889,7 @@ handle_face_prop (struct it *it)
            {
              int prev_face_id = face_before_it_pos (it);
 
-             old_face = FACE_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,
@@ -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);
-         struct face *old_face = FACE_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
@@ -4847,7 +4848,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          it->font_height = XCAR (XCDR (spec));
          if (!NILP (it->font_height))
            {
-             struct face *face = FACE_FROM_ID (it->f, it->face_id);
              int new_height = -1;
 
              if (CONSP (it->font_height)
@@ -4866,6 +4866,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                {
                  /* Call function with current height as argument.
                     Value is the new height.  */
+                 struct face *face = FACE_FROM_ID (it->f, it->face_id);
                  Lisp_Object height;
                  height = safe_call1 (it->font_height,
                                       face->lface[LFACE_HEIGHT_INDEX]);
@@ -4887,6 +4888,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
                  /* Evaluate IT->font_height with `height' bound to the
                     current specified height to get the new height.  */
                  ptrdiff_t count = SPECPDL_INDEX ();
+                 struct face *face = FACE_FROM_ID (it->f, it->face_id);
 
                  specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
                  value = safe_eval (it->font_height);
@@ -5016,8 +5018,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
          || EQ (XCAR (spec), Qright_fringe))
       && CONSP (XCDR (spec)))
     {
-      int fringe_bitmap;
-
       if (it)
        {
          if (!FRAME_WINDOW_P (it->f))
@@ -5042,8 +5042,8 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 
 #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.  */
        {
@@ -6096,7 +6096,7 @@ pop_it (struct it *it)
       break;
     case GET_FROM_STRING:
       {
-       struct face *face = FACE_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
@@ -6777,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,                  \
-                                FACE_FROM_ID ((IT)->f, (IT)->face_id), \
+                                FACE_FROM_ID_OR_NULL ((IT)->f,         \
+                                                      (IT)->face_id),  \
                                 (IT)->string)))
 
 
@@ -7206,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);
-         struct face *face = FACE_FROM_ID (it->f, face_id);
+         struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
 
          if (face)
            {
@@ -7739,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.  */
-      this_face = FACE_FROM_ID (it->f, it->face_id);
-      prev_face = FACE_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
@@ -7765,7 +7766,7 @@ next_element_from_display_vector (struct it *it)
                                            it->saved_face_id);
            }
        }
-      next_face = FACE_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));
@@ -8557,7 +8558,8 @@ move_it_in_display_line_to (struct it *it,
   void *ppos_data = NULL;
   bool may_wrap = false;
   enum it_method prev_method = it->method;
-  ptrdiff_t closest_pos IF_LINT (= 0), prev_pos = IT_CHARPOS (*it);
+  ptrdiff_t closest_pos UNINIT;
+  ptrdiff_t prev_pos = IT_CHARPOS (*it);
   bool saw_smaller_pos = prev_pos < to_charpos;
 
   /* Don't produce glyphs in produce_glyphs.  */
@@ -8608,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.  */
-  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))
@@ -8809,6 +8810,8 @@ move_it_in_display_line_to (struct it *it,
                              ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
                              : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
+                 bool moved_forward = false;
+
                  if (/* IT->hpos == 0 means the very first glyph
                         doesn't fit on the line, e.g. a wide image.  */
                      it->hpos == 0
@@ -8827,16 +8830,37 @@ move_it_in_display_line_to (struct it *it,
                             now that we know it fits in this row.  */
                          if (BUFFER_POS_REACHED_P ())
                            {
+                             bool can_wrap = true;
+
+                             /* If we are at a whitespace character
+                                that barely fits on this screen line,
+                                but the next character is also
+                                whitespace, we cannot wrap here.  */
+                             if (it->line_wrap == WORD_WRAP
+                                 && wrap_it.sp >= 0
+                                 && may_wrap
+                                 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                               {
+                                 struct it tem_it;
+                                 void *tem_data = NULL;
+
+                                 SAVE_IT (tem_it, *it, tem_data);
+                                 set_iterator_to_next (it, true);
+                                 if (get_next_display_element (it)
+                                     && IT_DISPLAYING_WHITESPACE (it))
+                                   can_wrap = false;
+                                 RESTORE_IT (it, &tem_it, tem_data);
+                               }
                              if (it->line_wrap != WORD_WRAP
                                  || wrap_it.sp < 0
-                                 /* If we've just found whitespace to
-                                    wrap, effectively ignore the
-                                    previous wrap point -- it is no
-                                    longer relevant, but we won't
-                                    have an opportunity to update it,
-                                    since we've reached the edge of
-                                    this screen line.  */
-                                 || (may_wrap
+                                 /* If we've just found whitespace
+                                    where we can wrap, effectively
+                                    ignore the previous wrap point --
+                                    it is no longer relevant, but we
+                                    won't have an opportunity to
+                                    update it, since we've reached
+                                    the edge of this screen line.  */
+                                 || (may_wrap && can_wrap
                                      && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
                                {
                                  it->hpos = hpos_before_this_char;
@@ -8879,6 +8903,7 @@ move_it_in_display_line_to (struct it *it,
                                  result = MOVE_POS_MATCH_OR_ZV;
                                  break;
                                }
+                             moved_forward = true;
                              if (BUFFER_POS_REACHED_P ())
                                {
                                  if (ITERATOR_AT_END_OF_LINE_P (it))
@@ -8906,7 +8931,14 @@ move_it_in_display_line_to (struct it *it,
                     longer relevant, but we won't have an opportunity
                     to update it, since we are done with this screen
                     line.  */
-                 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+                 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
+                     /* If the character after the one which set the
+                        may_wrap flag is also whitespace, we can't
+                        wrap here, since the screen line cannot be
+                        wrapped in the middle of whitespace.
+                        Therefore, wrap_it _is_ relevant in that
+                        case.  */
+                     && !(moved_forward && IT_DISPLAYING_WHITESPACE (it)))
                    {
                      /* If we've found TO_X, go back there, as we now
                         know the last word fits on this screen line.  */
@@ -9005,6 +9037,11 @@ move_it_in_display_line_to (struct it *it,
            }
          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;
        }
 
@@ -9087,9 +9124,18 @@ move_it_in_display_line_to (struct it *it,
 
 #undef BUFFER_POS_REACHED_P
 
-  /* If we scanned beyond to_pos and didn't find a point to wrap at,
-     restore the saved iterator.  */
-  if (atpos_it.sp >= 0)
+  /* If we scanned beyond TO_POS, restore the saved iterator either to
+     the wrap point (if found), or to atpos/atx location.  We decide which
+     data to use to restore the saved iterator state by their X coordinates,
+     since buffer positions might increase non-monotonically with screen
+     coordinates due to bidi reordering.  */
+  if (result == MOVE_LINE_CONTINUED
+      && it->line_wrap == WORD_WRAP
+      && wrap_it.sp >= 0
+      && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
+         || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
+    RESTORE_IT (it, &wrap_it, wrap_data);
+  else if (atpos_it.sp >= 0)
     RESTORE_IT (it, &atpos_it, atpos_data);
   else if (atx_it.sp >= 0)
     RESTORE_IT (it, &atx_it, atx_data);
@@ -9934,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,
-        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.  */
-  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))
@@ -11660,7 +11709,7 @@ x_consider_frame_title (Lisp_Object frame)
   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;
@@ -11677,7 +11726,7 @@ x_consider_frame_title (Lisp_Object frame)
          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;
        }
@@ -11740,13 +11789,6 @@ prepare_menu_bars (void)
 {
   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))
     {
@@ -11787,7 +11829,7 @@ prepare_menu_bars (void)
              && !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
@@ -11824,7 +11866,7 @@ prepare_menu_bars (void)
          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
@@ -15464,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
-   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)
 {
-  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);
@@ -15497,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,
-         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;
 
@@ -15510,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.  */
-         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;
+             if (CHARPOS (pos) <= PT)
+               pos_before_pt = pos;
              pos = it.current.pos;
              if (it.line_wrap == WORD_WRAP)
                {
@@ -15538,6 +15588,13 @@ compute_window_start_on_continuation_line (struct window *w)
                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;
@@ -18662,7 +18719,7 @@ try_window_id (struct window *w)
       eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
       row = find_last_row_displaying_text (w->current_matrix, &it,
                                           first_unchanged_at_end_row);
-      eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
+      eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
       adjust_window_ends (w, row, true);
       eassert (w->window_end_bytepos >= 0);
       IF_DEBUG (debug_method_add (w, "A"));
@@ -18692,10 +18749,9 @@ try_window_id (struct window *w)
       struct glyph_row *current_row = current_matrix->rows + vpos;
       struct glyph_row *desired_row = desired_matrix->rows + vpos;
 
-      for (row = NULL;
-          row == NULL && vpos >= first_vpos;
-          --vpos, --current_row, --desired_row)
+      for (row = NULL; !row; --vpos, --current_row, --desired_row)
        {
+         eassert (first_vpos <= vpos);
          if (desired_row->enabled_p)
            {
              if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
@@ -18705,7 +18761,6 @@ try_window_id (struct window *w)
            row  = current_row;
        }
 
-      eassert (row != NULL);
       w->window_end_vpos = vpos + 1;
       w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
@@ -19469,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 glyph *g;
 
          saved_object = it->object;
          saved_pos = it->position;
@@ -19505,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.  */
-         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)
            {
@@ -19630,15 +19684,15 @@ extend_face_to_end_of_line (struct it *it)
     return;
 
   /* The default face, possibly remapped. */
-  default_face = FACE_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.  */
-  if (it->face_before_selective_p)
-    face = FACE_FROM_ID (f, it->saved_face_id);
-  else
-    face = FACE_FROM_ID (f, 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)
@@ -20378,16 +20432,16 @@ display_line (struct it *it)
   struct it wrap_it;
   void *wrap_data = NULL;
   bool may_wrap = false;
-  int wrap_x IF_LINT (= 0);
+  int wrap_x UNINIT;
   int wrap_row_used = -1;
-  int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0);
-  int wrap_row_phys_ascent IF_LINT (= 0), wrap_row_phys_height IF_LINT (= 0);
-  int wrap_row_extra_line_spacing IF_LINT (= 0);
-  ptrdiff_t wrap_row_min_pos IF_LINT (= 0), wrap_row_min_bpos IF_LINT (= 0);
-  ptrdiff_t wrap_row_max_pos IF_LINT (= 0), wrap_row_max_bpos IF_LINT (= 0);
+  int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
+  int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
+  int wrap_row_extra_line_spacing UNINIT;
+  ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
+  ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
   int cvpos;
   ptrdiff_t min_pos = ZV + 1, max_pos = 0;
-  ptrdiff_t min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0);
+  ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
   bool pending_handle_line_prefix = false;
 
   /* We always start displaying at hpos zero even if hscrolled.  */
@@ -21804,7 +21858,6 @@ Value is the new character position of point.  */)
        }
 
       /* 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
@@ -21861,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;
        }
-      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
@@ -24612,7 +24663,6 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
   face = FACE_FROM_ID (f, glyph->face_id);
 
   /* Make sure X resources of the face are allocated.  */
-  eassert (face != NULL);
   prepare_face_for_display (f, face);
 
   if (face->font)
@@ -25337,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;                      \
-    struct face *base_face = FACE_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;                                                       \
@@ -25558,7 +25608,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
     {
       struct glyph_string *h, *t;
       Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-      int mouse_beg_col IF_LINT (= 0), mouse_end_col IF_LINT (= 0);
+      int mouse_beg_col UNINIT, mouse_end_col UNINIT;
       bool check_mouse_face = false;
       int dummy_x = 0;
 
@@ -25960,7 +26010,6 @@ produce_image_glyph (struct it *it)
   eassert (it->what == IT_IMAGE);
 
   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);
 
@@ -25975,7 +26024,6 @@ produce_image_glyph (struct it *it)
     }
 
   img = IMAGE_FROM_ID (it->f, it->image_id);
-  eassert (img);
   /* Make sure X resources of the image is loaded.  */
   prepare_image_for_display (it->f, img);
 
@@ -26131,7 +26179,6 @@ produce_xwidget_glyph (struct it *it)
   eassert (it->what == IT_XWIDGET);
 
   struct face *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);
 
@@ -26657,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);
-      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)
@@ -27308,18 +27351,21 @@ x_produce_glyphs (struct it *it)
          int leftmost, rightmost, lowest, highest;
          int lbearing, rbearing;
          int i, width, ascent, descent;
-         int c IF_LINT (= 0); /* cmp->glyph_len can't be zero; see Bug#8512 */
+         int c;
          XChar2b char2b;
          struct font_metrics *pcm;
          ptrdiff_t pos;
 
-         for (glyph_len = cmp->glyph_len; glyph_len > 0; glyph_len--)
-           if ((c = COMPOSITION_GLYPH (cmp, glyph_len - 1)) != '\t')
-             break;
+         eassume (0 < glyph_len); /* See Bug#8512.  */
+         do
+           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++)
            {
-             if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
+             c = COMPOSITION_GLYPH (cmp, i);
+             if (c != '\t')
                break;
              cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
            }
@@ -28018,7 +28064,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
              /* Using a block cursor on large images can be very annoying.
                 So use a hollow cursor for "large" images.
                 If image is not transparent (no mask), also use hollow cursor.  */
-             struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+             struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
              if (img != NULL && IMAGEP (img->spec))
                {
                  /* Arbitrarily, interpret "Large" as >32x32 and >NxN
@@ -28643,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)
        {
+#ifdef HAVE_WINDOW_SYSTEM
          int hpos = w->phys_cursor.hpos;
 
          /* When the window is hscrolled, cursor hpos can legitimately be
@@ -28663,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 ();
-       }
 #endif /* HAVE_WINDOW_SYSTEM */
+       }
     }
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -29604,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));
 }
+#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)
 {
+#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;
@@ -29626,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;
-#ifdef HAVE_X_WINDOWS
+# ifdef HAVE_X_WINDOWS
       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))
@@ -29640,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);
+#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
@@ -29665,12 +29715,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
   int dx, dy, width, height;
   ptrdiff_t charpos;
   Lisp_Object string, object = Qnil;
-  Lisp_Object pos IF_LINT (= Qnil), help;
-
+  Lisp_Object pos UNINIT;
   Lisp_Object mouse_face;
   int original_x_pixel = x;
   struct glyph * glyph = NULL, * row_start_glyph = NULL;
-  struct glyph_row *row IF_LINT (= 0);
+  struct glyph_row *row UNINIT;
 
   if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
     {
@@ -29710,7 +29759,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
                                     &object, &dx, &dy, &width, &height);
     }
 
-  help = Qnil;
+  Lisp_Object help = Qnil;
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (IMAGEP (object))
@@ -29958,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);
 
-#ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_WINDOW_P (f))
-    define_frame_cursor1 (f, cursor, pointer);
-#endif
+  define_frame_cursor1 (f, cursor, pointer);
 }
 
 
@@ -30105,7 +30151,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
       /* Look for :pointer property on image.  */
       if (glyph != NULL && glyph->type == IMAGE_GLYPH)
        {
-         struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+         struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
          if (img != NULL && IMAGEP (img->spec))
            {
              Lisp_Object image_map, hotspot;
@@ -30166,15 +30212,15 @@ note_mouse_highlight (struct frame *f, int x, int y)
        {
          if (clear_mouse_face (hlinfo))
            cursor = No_Cursor;
-#ifdef HAVE_WINDOW_SYSTEM
          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;
-           }
 #endif
+           }
          goto set_cursor;
        }
 
@@ -30285,8 +30331,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
            {
              /* The mouse-highlighting, if any, comes from an overlay
                 or text property in the buffer.  */
-             Lisp_Object buffer IF_LINT (= Qnil);
-             Lisp_Object disp_string IF_LINT (= Qnil);
+             Lisp_Object buffer UNINIT;
+             Lisp_Object disp_string UNINIT;
 
              if (STRINGP (object))
                {
@@ -30486,15 +30532,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
     }
 
  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);
 }