]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Fix vertical layout calculations when newline has line-height property
[gnu-emacs] / src / xdisp.c
index 10a0cf24b4aa46bec148bff4d0ac98c9fe87bbca..da0e84f00432247cee74fd5e108e24403bc56de6 100644 (file)
@@ -5017,8 +5017,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,6 +5040,8 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
        return 1;
 
 #ifdef HAVE_WINDOW_SYSTEM
+      int fringe_bitmap;
+
       value = XCAR (XCDR (spec));
       if (!SYMBOLP (value)
          || !(fringe_bitmap = lookup_fringe_bitmap (value)))
@@ -8558,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.  */
@@ -8810,6 +8811,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
@@ -8828,16 +8831,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;
@@ -8880,6 +8904,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))
@@ -8907,7 +8932,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.  */
@@ -9006,6 +9038,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;
        }
 
@@ -9088,9 +9125,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);
@@ -19468,7 +19514,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;
@@ -19504,7 +19549,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)
            {
@@ -20376,16 +20421,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.  */
@@ -21646,7 +21691,9 @@ Value is the new character position of point.  */)
       int pt_x, target_x, pixel_width, pt_vpos;
       bool at_eol_p;
       bool overshoot_expected = false;
+#ifdef HAVE_WINDOW_SYSTEM
       bool target_is_eol_p = false;
+#endif
 
       /* Setup the arena.  */
       SET_TEXT_POS (pt, PT, PT_BYTE);
@@ -21761,7 +21808,9 @@ 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);
+#ifdef HAVE_WINDOW_SYSTEM
              target_is_eol_p = true;
+#endif
              /* 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
@@ -25555,7 +25604,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;
 
@@ -27302,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);
+         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;
            }
@@ -28550,7 +28602,11 @@ static void
 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
 {
   struct window *w = XWINDOW (hlinfo->mouse_face_window);
+#ifdef HAVE_WINDOW_SYSTEM
   struct frame *f = XFRAME (WINDOW_FRAME (w));
+#else
+  (void) XFRAME (WINDOW_FRAME (w));
+#endif
 
   if (/* If window is in the process of being destroyed, don't bother
         to do anything.  */
@@ -28561,7 +28617,9 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
         anymore.  This can happen when a window is split.  */
       && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
     {
+#ifdef HAVE_WINDOW_SYSTEM
       bool phys_cursor_on_p = w->phys_cursor_on_p;
+#endif
       struct glyph_row *row, *first, *last;
 
       first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
@@ -29653,18 +29711,17 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
 #ifdef HAVE_WINDOW_SYSTEM
   Display_Info *dpyinfo;
-#endif
   Cursor cursor = No_Cursor;
   Lisp_Object pointer = Qnil;
+#endif
   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)
     {
@@ -29704,7 +29761,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))
@@ -29907,8 +29964,12 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
               && hlinfo->mouse_face_beg_row == vpos )
            return;
 
+#ifdef HAVE_WINDOW_SYSTEM
          if (clear_mouse_face (hlinfo))
            cursor = No_Cursor;
+#else
+         (void) clear_mouse_face (hlinfo);
+#endif
 
          if (!row->reversed_p)
            {
@@ -29942,8 +30003,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
          show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
          mouse_face_shown = true;
 
+#ifdef HAVE_WINDOW_SYSTEM
          if (NILP (pointer))
            pointer = Qhand;
+#endif
        }
     }
 
@@ -29974,8 +30037,10 @@ note_mouse_highlight (struct frame *f, int x, int y)
   enum window_part part = ON_NOTHING;
   Lisp_Object window;
   struct window *w;
+#ifdef HAVE_WINDOW_SYSTEM
   Cursor cursor = No_Cursor;
   Lisp_Object pointer = Qnil;  /* Takes precedence over cursor!  */
+#endif
   struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd.  */
@@ -30158,9 +30223,11 @@ note_mouse_highlight (struct frame *f, int x, int y)
              && glyph->type == STRETCH_GLYPH
              && glyph->avoid_cursor_p))
        {
+#ifndef HAVE_WINDOW_SYSTEM
+         (void) clear_mouse_face (hlinfo);
+#else  /* HAVE_WINDOW_SYSTEM */
          if (clear_mouse_face (hlinfo))
            cursor = No_Cursor;
-#ifdef HAVE_WINDOW_SYSTEM
          if (FRAME_WINDOW_P (f) && NILP (pointer))
            {
              if (area != TEXT_AREA)
@@ -30168,7 +30235,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
              else
                pointer = Vvoid_text_area_pointer;
            }
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
          goto set_cursor;
        }
 
@@ -30213,8 +30280,10 @@ note_mouse_highlight (struct frame *f, int x, int y)
 
       same_region = coords_in_mouse_face_p (w, hpos, vpos);
 
+#ifdef HAVE_WINDOW_SYSTEM
       if (same_region)
        cursor = No_Cursor;
+#endif
 
       /* Check mouse-face highlighting.  */
       if (! same_region
@@ -30241,8 +30310,12 @@ note_mouse_highlight (struct frame *f, int x, int y)
          hlinfo->mouse_face_overlay = overlay;
 
          /* Clear the display of the old active region, if any.  */
+#ifdef HAVE_WINDOW_SYSTEM
          if (clear_mouse_face (hlinfo))
            cursor = No_Cursor;
+#else
+         (void) clear_mouse_face (hlinfo);
+#endif
 
          /* If no overlay applies, get a text property.  */
          if (NILP (overlay))
@@ -30273,14 +30346,16 @@ note_mouse_highlight (struct frame *f, int x, int y)
                = face_at_string_position (w, object, pos, 0, &ignore,
                                           glyph->face_id, true);
              show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
+#ifdef HAVE_WINDOW_SYSTEM
              cursor = No_Cursor;
+#endif
            }
          else
            {
              /* 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))
                {
@@ -30357,7 +30432,9 @@ note_mouse_highlight (struct frame *f, int x, int y)
                                              : XFASTINT (after),
                                              before_string, after_string,
                                              disp_string);
+#ifdef HAVE_WINDOW_SYSTEM
                  cursor = No_Cursor;
+#endif
                }
            }
        }