changeset 109886:43a4dcd16d73

Fix mouse clicks, drag, and highlight in R2L lines. dispnew.c (buffer_posn_from_coords): Fix calculation of buffer position for R2L lines by mirroring the pixel position wrt the text are box. Improve commentary.
author Eli Zaretskii <eliz@gnu.org>
date Fri, 20 Aug 2010 17:19:39 +0300
parents 42a68d95e799
children b6004420857b
files src/ChangeLog src/dispnew.c
diffstat 2 files changed, 38 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Aug 20 14:02:43 2010 +0200
+++ b/src/ChangeLog	Fri Aug 20 17:19:39 2010 +0300
@@ -1,3 +1,9 @@
+2010-08-20  Eli Zaretskii  <eliz@gnu.org>
+
+	* dispnew.c (buffer_posn_from_coords): Fix calculation of buffer
+	position for R2L lines by mirroring the pixel position wrt the
+	text are box.  Improve commentary.
+
 2010-08-20  Andreas Schwab  <schwab@linux-m68k.org>
 
 	* image.c (imagemagick_clear_image): Remove debugging output.
--- a/src/dispnew.c	Fri Aug 20 14:02:43 2010 +0200
+++ b/src/dispnew.c	Fri Aug 20 17:19:39 2010 +0300
@@ -5351,9 +5351,15 @@
  ***********************************************************************/
 
 /* Determine what's under window-relative pixel position (*X, *Y).
-   Return the object (string or buffer) that's there.
+   Return the OBJECT (string or buffer) that's there.
    Return in *POS the position in that object.
-   Adjust *X and *Y to character positions.  */
+   Adjust *X and *Y to character positions.
+   Return in *DX and *DY the pixel coordinates of the click,
+   relative to the top left corner of OBJECT, or relative to
+   the top left corner of the character glyph at (*X, *Y)
+   if OBJECT is nil.
+   Return WIDTH and HEIGHT of the object at (*X, *Y), or zero
+   if the coordinates point to an empty area of the display.  */
 
 Lisp_Object
 buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *pos, Lisp_Object *object, int *dx, int *dy, int *width, int *height)
@@ -5366,7 +5372,7 @@
 #ifdef HAVE_WINDOW_SYSTEM
   struct image *img = 0;
 #endif
-  int x0, x1;
+  int x0, x1, to_x;
 
   /* We used to set current_buffer directly here, but that does the
      wrong thing with `face-remapping-alist' (bug#2044).  */
@@ -5377,8 +5383,29 @@
   start_display (&it, w, startp);
 
   x0 = *x - WINDOW_LEFT_MARGIN_WIDTH (w);
-  move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1,
-	      MOVE_TO_X | MOVE_TO_Y);
+
+  /* First, move to the beginning of the row corresponding to *Y.  We
+     need to be in that row to get the correct value of base paragraph
+     direction for the paragraph at *X.  */
+  move_it_to (&it, -1, 0, *y, -1, MOVE_TO_X | MOVE_TO_Y);
+
+  /* TO_X is the pixel position that the iterator will compute for the
+     glyph at *X.  This is because iterator positions are not offset
+     due to hscroll.  */
+  to_x = x0 + it.first_visible_x;
+  if (it.bidi_it.paragraph_dir == R2L)
+    /* For lines in an R2L paragraph, we need to mirror TO_X wrt the
+       text area.  This is because the iterator, even in R2L
+       paragraphs, delivers glyphs as if they started at the left
+       margin of the window.  (When we actually produce glyphs for
+       display, we reverse their order in PRODUCE_GLYPHS, but the
+       iterator doesn't know about that.)  The following line adjusts
+       the pixel position to the iterator geometry, which is what
+       move_it_* routines use.  */
+    to_x = window_box_width (w, TEXT_AREA) - to_x;
+
+  /* Now move horizontally in the row to the glyph under *X. */
+  move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X);
 
   Fset_buffer (old_current_buffer);