changeset 111417:6316c70b291e

Support R2L lines in tool-tip text. xfns.c (Fx_show_tip): If any of the tool-tip text lines is R2L, adjust width of tool-tip frame to the width of text, excluding the stretch glyph at the beginning of R2L glyph rows. w32fns.c (Fx_show_tip): Likewise.
author Eli Zaretskii <eliz@gnu.org>
date Sat, 06 Nov 2010 15:45:37 +0200
parents 7a88e72dff57
children 1542066c2762
files src/ChangeLog src/w32fns.c src/xfns.c
diffstat 3 files changed, 140 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sat Nov 06 13:08:58 2010 +0100
+++ b/src/ChangeLog	Sat Nov 06 15:45:37 2010 +0200
@@ -1,3 +1,11 @@
+2010-11-06  Eli Zaretskii  <eliz@gnu.org>
+
+	* xfns.c (Fx_show_tip): If any of the tool-tip text lines is R2L,
+	adjust width of tool-tip frame to the width of text, excluding the
+	stretch glyph at the beginning of R2L glyph rows.
+
+	* w32fns.c (Fx_show_tip): Likewise.
+
 2010-11-06  Jan Djärv  <jan.h.d@swipnet.se>
 
 	* nsfont.m: Include termchar for new mouse-highlight.
--- a/src/w32fns.c	Sat Nov 06 13:08:58 2010 +0100
+++ b/src/w32fns.c	Sat Nov 06 15:45:37 2010 +0200
@@ -5657,7 +5657,7 @@
   int root_x, root_y;
   struct buffer *old_buffer;
   struct text_pos pos;
-  int i, width, height;
+  int i, width, height, seen_reversed_p;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
   int count = SPECPDL_INDEX ();
@@ -5787,7 +5787,7 @@
   try_window (FRAME_ROOT_WINDOW (f), pos, 0);
 
   /* Compute width and height of the tooltip.  */
-  width = height = 0;
+  width = height = seen_reversed_p = 0;
   for (i = 0; i < w->desired_matrix->nrows; ++i)
     {
       struct glyph_row *row = &w->desired_matrix->rows[i];
@@ -5801,24 +5801,83 @@
       /* Let the row go over the full width of the frame.  */
       row->full_width_p = 1;
 
-#ifdef TODO /* Investigate why some fonts need more width than is
-	       calculated for some tooltips.  */
-      /* There's a glyph at the end of rows that is use to place
-	 the cursor there.  Don't include the width of this glyph.  */
+      row_width = row->pixel_width;
       if (row->used[TEXT_AREA])
 	{
-	  last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
-	  row_width = row->pixel_width - last->pixel_width;
+	  if (!row->reversed_p)
+	    {
+#ifdef TODO   /* Investigate why some fonts need more width than is
+		 calculated for some tooltips.  */
+
+	      /* There's a glyph at the end of rows that is used to
+		 place the cursor there.  Don't include the width of
+		 this glyph.  */
+	      last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
+	      if (INTEGERP (last->object))
+		row_width -= last->pixel_width;
+#endif
+	    }
+	  else
+	    {
+	      /* There could be a stretch glyph at the beginning of R2L
+		 rows that is produced by extend_face_to_end_of_line.
+		 Don't count that glyph.  */
+	      struct glyph *g = row->glyphs[TEXT_AREA];
+
+	      if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
+		{
+		  row_width -= g->pixel_width;
+		  seen_reversed_p = 1;
+		}
+	    }
 	}
-      else
-#endif
-	row_width = row->pixel_width;
 
       /* TODO: find why tips do not draw along baseline as instructed.  */
       height += row->height;
       width = max (width, row_width);
     }
 
+  /* If we've seen partial-length R2L rows, we need to re-adjust the
+     tool-tip frame width and redisplay it again, to avoid over-wide
+     tips due to the stretch glyph that extends R2L lines to full
+     width of the frame.  */
+  if (seen_reversed_p)
+    {
+      /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
+	 not in pixels.  */
+      width /= WINDOW_FRAME_COLUMN_WIDTH (w);
+      w->total_cols = make_number (width);
+      FRAME_TOTAL_COLS (f) = width;
+      adjust_glyphs (f);
+      clear_glyph_matrix (w->desired_matrix);
+      clear_glyph_matrix (w->current_matrix);
+      try_window (FRAME_ROOT_WINDOW (f), pos, 0);
+      width = height = 0;
+      /* Recompute width and height of the tooltip.  */
+      for (i = 0; i < w->desired_matrix->nrows; ++i)
+	{
+	  struct glyph_row *row = &w->desired_matrix->rows[i];
+	  struct glyph *last;
+	  int row_width;
+
+	  if (!row->enabled_p || !row->displays_text_p)
+	    break;
+	  row->full_width_p = 1;
+	  row_width = row->pixel_width;
+#ifdef TODO /* See above.  */
+	  if (row->used[TEXT_AREA] && !row->reversed_p)
+	    {
+	      last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
+	      if (INTEGERP (last->object))
+		row_width -= last->pixel_width;
+	    }
+#endif
+
+	  height += row->height;
+	  width = max (width, row_width);
+	}
+    }
+
   /* Add the frame's internal border to the width and height the X
      window should have.  */
   height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
--- a/src/xfns.c	Sat Nov 06 13:08:58 2010 +0100
+++ b/src/xfns.c	Sat Nov 06 15:45:37 2010 +0200
@@ -5017,7 +5017,7 @@
   int root_x, root_y;
   struct buffer *old_buffer;
   struct text_pos pos;
-  int i, width, height;
+  int i, width, height, seen_reversed_p;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   int old_windows_or_buffers_changed = windows_or_buffers_changed;
   int count = SPECPDL_INDEX ();
@@ -5158,7 +5158,7 @@
   try_window (FRAME_ROOT_WINDOW (f), pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
 
   /* Compute width and height of the tooltip.  */
-  width = height = 0;
+  width = height = seen_reversed_p = 0;
   for (i = 0; i < w->desired_matrix->nrows; ++i)
     {
       struct glyph_row *row = &w->desired_matrix->rows[i];
@@ -5173,19 +5173,74 @@
       row->full_width_p = 1;
 
       row_width = row->pixel_width;
-      /* There's a glyph at the end of rows that is used to place
-	 the cursor there.  Don't include the width of this glyph.  */
       if (row->used[TEXT_AREA])
 	{
-	  last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
-	  if (INTEGERP (last->object))
-	    row_width -= last->pixel_width;
+	  /* There's a glyph at the end of rows that is used to place
+	     the cursor there.  Don't include the width of this glyph.  */
+	  if (!row->reversed_p)
+	    {
+	      last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
+	      if (INTEGERP (last->object))
+		row_width -= last->pixel_width;
+	    }
+	  else
+	    {
+	      /* There could be a stretch glyph at the beginning of R2L
+		 rows that is produced by extend_face_to_end_of_line.
+		 Don't count that glyph.  */
+	      struct glyph *g = row->glyphs[TEXT_AREA];
+
+	      if (g->type == STRETCH_GLYPH && INTEGERP (g->object))
+		{
+		  row_width -= g->pixel_width;
+		  seen_reversed_p = 1;
+		}
+	    }
 	}
 
       height += row->height;
       width = max (width, row_width);
     }
 
+  /* If we've seen partial-length R2L rows, we need to re-adjust the
+     tool-tip frame width and redisplay it again, to avoid over-wide
+     tips due to the stretch glyph that extends R2L lines to full
+     width of the frame.  */
+  if (seen_reversed_p)
+    {
+      /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
+	 not in pixels.  */
+      width /= WINDOW_FRAME_COLUMN_WIDTH (w);
+      w->total_cols = make_number (width);
+      FRAME_TOTAL_COLS (f) = width;
+      adjust_glyphs (f);
+      clear_glyph_matrix (w->desired_matrix);
+      clear_glyph_matrix (w->current_matrix);
+      try_window (FRAME_ROOT_WINDOW (f), pos, 0);
+      width = height = 0;
+      /* Recompute width and height of the tooltip.  */
+      for (i = 0; i < w->desired_matrix->nrows; ++i)
+	{
+	  struct glyph_row *row = &w->desired_matrix->rows[i];
+	  struct glyph *last;
+	  int row_width;
+
+	  if (!row->enabled_p || !row->displays_text_p)
+	    break;
+	  row->full_width_p = 1;
+	  row_width = row->pixel_width;
+	  if (row->used[TEXT_AREA] && !row->reversed_p)
+	    {
+	      last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
+	      if (INTEGERP (last->object))
+		row_width -= last->pixel_width;
+	    }
+
+	  height += row->height;
+	  width = max (width, row_width);
+	}
+    }
+
   /* Add the frame's internal border to the width and height the X
      window should have.  */
   height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);