]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix 'window-text-pixel-width' when starting from display property
authorEli Zaretskii <eliz@gnu.org>
Tue, 12 Apr 2022 14:05:15 +0000 (17:05 +0300)
committerEli Zaretskii <eliz@gnu.org>
Tue, 12 Apr 2022 14:05:15 +0000 (17:05 +0300)
* src/xdisp.c (Fwindow_text_pixel_size): Handle the case where
there's a display property at START, and move_it_to overshoots.
Do not merge to master.  (Bug#54862)

src/xdisp.c

index 44f2536880b816b2dd4bc53cefa65b572bc819a2..15bb5eefb56ed16e7d551371404df9761de2e92e 100644 (file)
@@ -10788,11 +10788,51 @@ include the height of any of these, if present, in the return value.  */)
      non-zero X coordinate.  */
   reseat_at_previous_visible_line_start (&it);
   it.current_x = it.hpos = 0;
+
+  int start_x;
   if (IT_CHARPOS (it) != start)
-    move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
+    {
+      void *it1data = NULL;
+      struct it it1;
+
+      SAVE_IT (it1, it, it1data);
+      move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
+      /* We could have a display property at START, in which case
+        asking move_it_to to stop at START will overshoot and stop at
+        position after START.  So we try again, stopping before
+        START, and account for the width of the last buffer position
+        manually.  */
+      if (IT_CHARPOS (it) > start && start > BEGV)
+       {
+         ptrdiff_t it1pos = IT_CHARPOS (it1);
+         int it1_x = it1.current_x;
+
+         RESTORE_IT (&it, &it1, it1data);
+         /* If START - 1 is the beginning of screen line, move_it_to
+            will not move, so we need to use a lower-level
+            move_it_in_display_line subroutine, and tell it to move
+            just 1 pixel, so it stops at the next display element.  */
+         if (start - 1 > it1pos)
+           move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
+         else
+           move_it_in_display_line (&it, start, it1_x + 1,
+                                    MOVE_TO_POS | MOVE_TO_X);
+         start_x = it.current_x;
+         /* If we didn't change our buffer position, the pixel width
+            of what's here was not yet accounted for; do it manually.  */
+         if (IT_CHARPOS (it) == start - 1)
+           start_x += it.pixel_width;
+       }
+      else
+       {
+         start_x = it.current_x;
+         bidi_unshelve_cache (it1data, true);
+       }
+    }
+  else
+    start_x = it.current_x;
 
   /* Now move to TO.  */
-  int start_x = it.current_x;
   int move_op = MOVE_TO_POS | MOVE_TO_Y;
   int to_x = -1;
   it.current_y = start_y;