emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r108938: Fix bug #11832 with truncate


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r108938: Fix bug #11832 with truncated lines when fringes are disabled on GUI frames.
Date: Sat, 07 Jul 2012 19:36:02 +0300
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 108938
fixes bug: http://debbugs.gnu.org/11832
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Sat 2012-07-07 19:36:02 +0300
message:
  Fix bug #11832 with truncated lines when fringes are disabled on GUI frames.
  
   src/xdisp.c (init_iterator): Get dimensions of truncation and
   continuation glyphs even if on GUI frames.  Adjust
   it->last_visible_x on GUI frames when the left or right fringes,
   or both, are absent.
   (start_display, move_it_in_display_line_to): Handle the case of a
   GUI frame without a fringe to display continuation or truncation
   glyphs.
   (insert_left_trunc_glyphs): Support GUI frames: make sure
   truncation glyphs overwrite enough glyphs from the current line to
   have sufficient space in pixels.
   (display_line): Support truncation and continuation glyphs on GUI
   frames.  If some spare pixels are left on the line after inserting
   the truncation glyphs, fill that space with a stretch glyph of a
   suitably computed width.
   src/term.c (produce_special_glyphs): Call PRODUCE_GLYPHS, not
   produce_glyphs, to support GUI sessions.
modified:
  src/ChangeLog
  src/term.c
  src/xdisp.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-07-07 03:06:00 +0000
+++ b/src/ChangeLog     2012-07-07 16:36:02 +0000
@@ -1,3 +1,25 @@
+2012-07-07  Eli Zaretskii  <address@hidden>
+
+       Support truncation and continuation glyphs on GUI frames, when
+       fringes are disabled.  (Bug#11832)
+       * xdisp.c (init_iterator): Get dimensions of truncation and
+       continuation glyphs even if on GUI frames.  Adjust
+       it->last_visible_x on GUI frames when the left or right fringes,
+       or both, are absent.
+       (start_display, move_it_in_display_line_to): Handle the case of a
+       GUI frame without a fringe to display continuation or truncation
+       glyphs.
+       (insert_left_trunc_glyphs): Support GUI frames: make sure
+       truncation glyphs overwrite enough glyphs from the current line to
+       have sufficient space in pixels.
+       (display_line): Support truncation and continuation glyphs on GUI
+       frames.  If some spare pixels are left on the line after inserting
+       the truncation glyphs, fill that space with a stretch glyph of a
+       suitably computed width.
+
+       * term.c (produce_special_glyphs): Call PRODUCE_GLYPHS, not
+       produce_glyphs, to support GUI sessions.
+
 2012-07-07  Paul Eggert  <address@hidden>
 
        * sysdep.c (ULLONG_MAX): Define if not already defined (Bug#11781).

=== modified file 'src/term.c'
--- a/src/term.c        2012-07-05 18:35:48 +0000
+++ b/src/term.c        2012-07-07 16:36:02 +0000
@@ -1940,7 +1940,7 @@
   temp_it.face_id = GLYPH_FACE (glyph);
   temp_it.len = CHAR_BYTES (temp_it.c);
 
-  produce_glyphs (&temp_it);
+  PRODUCE_GLYPHS (&temp_it);
   it->pixel_width = temp_it.pixel_width;
   it->nglyphs = temp_it.pixel_width;
 }

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2012-07-05 18:35:48 +0000
+++ b/src/xdisp.c       2012-07-07 16:36:02 +0000
@@ -2731,30 +2731,27 @@
     it->line_wrap = TRUNCATE;
 
   /* Get dimensions of truncation and continuation glyphs.  These are
-     displayed as fringe bitmaps under X, so we don't need them for such
-     frames.  */
-  if (!FRAME_WINDOW_P (it->f))
-    {
-      if (it->line_wrap == TRUNCATE)
-       {
-         /* We will need the truncation glyph.  */
-         eassert (it->glyph_row == NULL);
-         produce_special_glyphs (it, IT_TRUNCATION);
-         it->truncation_pixel_width = it->pixel_width;
-       }
-      else
-       {
-         /* We will need the continuation glyph.  */
-         eassert (it->glyph_row == NULL);
-         produce_special_glyphs (it, IT_CONTINUATION);
-         it->continuation_pixel_width = it->pixel_width;
-       }
+     displayed as fringe bitmaps under X, but we need them for such
+     frames when the fringes are turned off.  */
+  if (it->line_wrap == TRUNCATE)
+    {
+      /* We will need the truncation glyph.  */
+      eassert (it->glyph_row == NULL);
+      produce_special_glyphs (it, IT_TRUNCATION);
+      it->truncation_pixel_width = it->pixel_width;
+    }
+  else
+    {
+      /* We will need the continuation glyph.  */
+      eassert (it->glyph_row == NULL);
+      produce_special_glyphs (it, IT_CONTINUATION);
+      it->continuation_pixel_width = it->pixel_width;
+    }
 
-      /* Reset these values to zero because the produce_special_glyphs
-        above has changed them.  */
-      it->pixel_width = it->ascent = it->descent = 0;
-      it->phys_ascent = it->phys_descent = 0;
-    }
+  /* Reset these values to zero because the produce_special_glyphs
+     above has changed them.  */
+  it->pixel_width = it->ascent = it->descent = 0;
+  it->phys_ascent = it->phys_descent = 0;
 
   /* Set this after getting the dimensions of truncation and
      continuation glyphs, so that we don't produce glyphs when calling
@@ -2783,11 +2780,14 @@
       it->last_visible_x = (it->first_visible_x
                            + window_box_width (w, TEXT_AREA));
 
-      /* If we truncate lines, leave room for the truncator glyph(s) at
+      /* If we truncate lines, leave room for the truncation glyph(s) at
         the right margin.  Otherwise, leave room for the continuation
-        glyph(s).  Truncation and continuation glyphs are not inserted
-        for window-based redisplay.  */
-      if (!FRAME_WINDOW_P (it->f))
+        glyph(s).  Done only if the window has no fringes.  Since we
+        don't know at this point whether there will be any R2L lines in
+        the window, we reserve space for truncation/continuation glyphs
+        even if only one of the fringes is absent.  */
+      if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
+         || (it->bidi_p && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
        {
          if (it->line_wrap == TRUNCATE)
            it->last_visible_x -= it->truncation_pixel_width;
@@ -2923,7 +2923,10 @@
                  /* Or it fits exactly and we're on a window
                     system frame.  */
                  || (new_x == it->last_visible_x
-                     && FRAME_WINDOW_P (it->f))))
+                     && FRAME_WINDOW_P (it->f)
+                     && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+                         ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                         : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
            {
              if ((it->current.dpvec_index >= 0
                   || it->current.overlay_string_index >= 0)
@@ -8327,7 +8330,10 @@
                      /* Or it fits exactly and we're on a window
                         system frame.  */
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f))))
+                         && FRAME_WINDOW_P (it->f)
+                         && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
                  if (/* IT->hpos == 0 means the very first glyph
                         doesn't fit on the line, e.g. a wide image.  */
@@ -8509,6 +8515,9 @@
          && it->current_x >= it->last_visible_x)
        {
          if (!FRAME_WINDOW_P (it->f)
+             || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
+                 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
              || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            {
              int at_eob_p = 0;
@@ -18203,11 +18212,8 @@
 }
 
 
-/* Insert truncation glyphs at the start of IT->glyph_row.  Truncation
-   glyphs are only inserted for terminal frames since we can't really
-   win with truncation glyphs when partially visible glyphs are
-   involved.  Which glyphs to insert is determined by
-   produce_special_glyphs.  */
+/* Insert truncation glyphs at the start of IT->glyph_row.  Which
+   glyphs to insert is determined by produce_special_glyphs.  */
 
 static void
 insert_left_trunc_glyphs (struct it *it)
@@ -18215,7 +18221,11 @@
   struct it truncate_it;
   struct glyph *from, *end, *to, *toend;
 
-  eassert (!FRAME_WINDOW_P (it->f));
+  eassert (!FRAME_WINDOW_P (it->f)
+          || (!it->glyph_row->reversed_p
+              && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
+          || (it->glyph_row->reversed_p
+              && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
 
   /* Get the truncation glyphs.  */
   truncate_it = *it;
@@ -18230,20 +18240,66 @@
   /* Overwrite glyphs from IT with truncation glyphs.  */
   if (!it->glyph_row->reversed_p)
     {
+      short tused = truncate_it.glyph_row->used[TEXT_AREA];
+
       from = truncate_it.glyph_row->glyphs[TEXT_AREA];
-      end = from + truncate_it.glyph_row->used[TEXT_AREA];
+      end = from + tused;
       to = it->glyph_row->glyphs[TEXT_AREA];
       toend = to + it->glyph_row->used[TEXT_AREA];
+      if (FRAME_WINDOW_P (it->f))
+       {
+         /* On GUI frames, when variable-size fonts are displayed,
+            the truncation glyphs may need more pixels than the row's
+            glyphs they overwrite.  We overwrite more glyphs to free
+            enough screen real estate, and enlarge the stretch glyph
+            on the right (see display_line), if there is one, to
+            preserve the screen position of the truncation glyphs on
+            the right.  */
+         int w = 0;
+         struct glyph *g = to;
+         short used;
+
+         while (g < toend && it->glyph_row->x + w < 0)
+           {
+             w += g->pixel_width;
+             ++g;
+           }
+         it->glyph_row->x = 0;
+         w = 0;
+         while (g < toend && w < it->truncation_pixel_width)
+           {
+             w += g->pixel_width;
+             ++g;
+           }
+         if (g - to - tused > 0)
+           {
+             memmove (to + tused, g, toend - g);
+             it->glyph_row->used[TEXT_AREA] -= g - to - tused;
+           }
+         used = it->glyph_row->used[TEXT_AREA];
+         if (it->glyph_row->truncated_on_right_p
+             && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
+             && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
+             == STRETCH_GLYPH)
+           {
+             int extra = w - it->truncation_pixel_width;
+
+             it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
+           }
+       }
 
       while (from < end)
        *to++ = *from++;
 
       /* There may be padding glyphs left over.  Overwrite them too.  */
-      while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+      if (!FRAME_WINDOW_P (it->f))
        {
-         from = truncate_it.glyph_row->glyphs[TEXT_AREA];
-         while (from < end)
-           *to++ = *from++;
+         while (to < toend && CHAR_GLYPH_PADDING_P (*to))
+           {
+             from = truncate_it.glyph_row->glyphs[TEXT_AREA];
+             while (from < end)
+               *to++ = *from++;
+           }
        }
 
       if (to > toend)
@@ -18251,22 +18307,48 @@
     }
   else
     {
+      short tused = truncate_it.glyph_row->used[TEXT_AREA];
+
       /* In R2L rows, overwrite the last (rightmost) glyphs, and do
         that back to front.  */
       end = truncate_it.glyph_row->glyphs[TEXT_AREA];
       from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
       toend = it->glyph_row->glyphs[TEXT_AREA];
       to = toend + it->glyph_row->used[TEXT_AREA] - 1;
+      if (FRAME_WINDOW_P (it->f))
+       {
+         int w = 0;
+         struct glyph *g = to;
+
+         while (g >= toend && w < it->truncation_pixel_width)
+           {
+             w += g->pixel_width;
+             --g;
+           }
+         if (to - g - tused > 0)
+           to = g + tused;
+         if (it->glyph_row->truncated_on_right_p
+             && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
+             && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
+           {
+             int extra = w - it->truncation_pixel_width;
+
+             it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
+           }
+       }
 
       while (from >= end && to >= toend)
        *to-- = *from--;
-      while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
+      if (!FRAME_WINDOW_P (it->f))
        {
-         from =
-           truncate_it.glyph_row->glyphs[TEXT_AREA]
-           + truncate_it.glyph_row->used[TEXT_AREA] - 1;
-         while (from >= end && to >= toend)
-           *to-- = *from--;
+         while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
+           {
+             from =
+               truncate_it.glyph_row->glyphs[TEXT_AREA]
+               + truncate_it.glyph_row->used[TEXT_AREA] - 1;
+             while (from >= end && to >= toend)
+               *to-- = *from--;
+           }
        }
       if (from >= end)
        {
@@ -19392,13 +19474,19 @@
                      new_x > it->last_visible_x
                      /* Or it fits exactly on a window system frame.  */
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f))))
+                         && FRAME_WINDOW_P (it->f)
+                         && (row->reversed_p
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
                {
                  /* End of a continued line.  */
 
                  if (it->hpos == 0
                      || (new_x == it->last_visible_x
-                         && FRAME_WINDOW_P (it->f)))
+                         && FRAME_WINDOW_P (it->f)
+                         && (row->reversed_p
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
                    {
                      /* Current glyph is the only one on the line or
                         fits exactly on the line.  We must continue
@@ -19509,6 +19597,10 @@
                         window system frames.  We leave the glyph in
                         this row and let it fill the row, but don't
                         consume the TAB.  */
+                     if ((row->reversed_p
+                          ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                          : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
+                       produce_special_glyphs (it, IT_CONTINUATION);
                      it->continuation_lines_width += it->last_visible_x;
                      row->ends_in_middle_of_char_p = 1;
                      row->continued_p = 1;
@@ -19526,7 +19618,10 @@
                      row->used[TEXT_AREA] = n_glyphs_before + i;
 
                      /* Display continuation glyphs.  */
-                     if (!FRAME_WINDOW_P (it->f))
+                     if (!FRAME_WINDOW_P (it->f)
+                         || (row->reversed_p
+                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
                        produce_special_glyphs (it, IT_CONTINUATION);
                      row->continued_p = 1;
 
@@ -19633,12 +19728,15 @@
       /* If we truncate lines, we are done when the last displayed
         glyphs reach past the right margin of the window.  */
       if (it->line_wrap == TRUNCATE
-         && (FRAME_WINDOW_P (it->f)
+         && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w)
              ? (it->current_x >= it->last_visible_x)
              : (it->current_x > it->last_visible_x)))
        {
          /* Maybe add truncation glyphs.  */
-         if (!FRAME_WINDOW_P (it->f))
+         if (!FRAME_WINDOW_P (it->f)
+             || (row->reversed_p
+                 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
            {
              int i, n;
 
@@ -19663,9 +19761,36 @@
                  i = row->used[TEXT_AREA] - (i + 1);
                }
 
-             for (n = row->used[TEXT_AREA]; i < n; ++i)
-               {
+             it->current_x = x_before;
+             if (!FRAME_WINDOW_P (it->f))
+               {
+                 for (n = row->used[TEXT_AREA]; i < n; ++i)
+                   {
+                     row->used[TEXT_AREA] = i;
+                     produce_special_glyphs (it, IT_TRUNCATION);
+                   }
+               }
+             else
+               {
+                 int stretch_width = it->last_visible_x - it->current_x;
+
                  row->used[TEXT_AREA] = i;
+                 if (stretch_width > 0)
+                   {
+                     struct face *face = FACE_FROM_ID (it->f, it->face_id);
+                     struct font *font =
+                       face->font ? face->font : FRAME_FONT (it->f);
+                     int stretch_ascent =
+                       (((it->ascent + it->descent)
+                         * FONT_BASE (font)) / FONT_HEIGHT (font));
+                     struct text_pos saved_pos = it->position;
+
+                     memset (&it->position, 0, sizeof it->position);
+                     append_stretch_glyph (it, make_number (0), stretch_width,
+                                           it->ascent + it->descent,
+                                           stretch_ascent);
+                     it->position = saved_pos;
+                   }
                  produce_special_glyphs (it, IT_TRUNCATION);
                }
            }
@@ -19684,6 +19809,7 @@
                  row->exact_window_width_line_p = 1;
                  goto at_end_of_line;
                }
+             it->current_x = x_before;
            }
 
          row->truncated_on_right_p = 1;
@@ -19691,7 +19817,6 @@
          reseat_at_next_visible_line_start (it, 0);
          row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
          it->hpos = hpos_before;
-         it->current_x = x_before;
          break;
        }
     }
@@ -19704,7 +19829,10 @@
   if (it->first_visible_x
       && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
     {
-      if (!FRAME_WINDOW_P (it->f))
+      if (!FRAME_WINDOW_P (it->f)
+         || (row->reversed_p
+             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+             : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
        insert_left_trunc_glyphs (it);
       row->truncated_on_left_p = 1;
     }
@@ -21913,7 +22041,10 @@
   if (it->first_visible_x
       && it_charpos > 0)
     {
-      if (!FRAME_WINDOW_P (it->f))
+      if (!FRAME_WINDOW_P (it->f)
+         || (row->reversed_p
+             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+             : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
        insert_left_trunc_glyphs (it);
       row->truncated_on_left_p = 1;
     }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]