emacs-diffs
[Top][All Lists]
Advanced

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

master c82afdc: A better fix for 'string-width'


From: Eli Zaretskii
Subject: master c82afdc: A better fix for 'string-width'
Date: Thu, 27 May 2021 05:26:12 -0400 (EDT)

branch: master
commit c82afdcc88442fcfb5ee076aef13dd9721a98192
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    A better fix for 'string-width'
    
    * src/character.c (lisp_string_width): Compute the width when
    automatic compositions can happen more accurately, by using the
    pixel widths of the grapheme clusters, divided by the default
    face's font width.  Disregard the current state of
    'auto-composition-mode', for consistency with 'current-column' .
---
 src/character.c | 44 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/src/character.c b/src/character.c
index e0978bb..5753e88 100644
--- a/src/character.c
+++ b/src/character.c
@@ -34,6 +34,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "lisp.h"
 #include "character.h"
 #include "buffer.h"
+#include "frame.h"
 #include "dispextern.h"
 #include "composite.h"
 #include "disptab.h"
@@ -343,6 +344,14 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, 
ptrdiff_t to,
   ptrdiff_t from_byte = i_byte;
   ptrdiff_t width = 0;
   struct Lisp_Char_Table *dp = buffer_display_table ();
+#ifdef HAVE_WINDOW_SYSTEM
+  struct frame *f =
+    (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
+    ? XFRAME (selected_frame)
+    : NULL;
+  int font_width = -1;
+  Lisp_Object default_font, frame_font;
+#endif
 
   eassert (precision <= 0 || (nchars && nbytes));
 
@@ -361,23 +370,40 @@ lisp_string_width (Lisp_Object string, ptrdiff_t from, 
ptrdiff_t to,
          chars = end - i;
          bytes = string_char_to_byte (string, end) - i_byte;
        }
-      else if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
-              && ! NILP (Vauto_composition_mode)
+#ifdef HAVE_WINDOW_SYSTEM
+      else if (f && FRAME_WINDOW_P (f)
+              && multibyte
               && find_automatic_composition (i, -1, &ignore, &end, &val, 
string)
               && end > i)
        {
-         int j;
-         for (thiswidth = 0, j = 0; j < LGSTRING_GLYPH_LEN (val); j++)
+         int pixelwidth = composition_gstring_width (val, 0,
+                                                     LGSTRING_GLYPH_LEN (val),
+                                                     NULL);
+         /* The below is somewhat expensive, so compute it only once
+            for the entire loop, and only if needed.  */
+         if (font_width < 0)
            {
-             Lisp_Object g = LGSTRING_GLYPH (val, j);
-
-             if (NILP (g))
-               break;
-             thiswidth += char_width (LGLYPH_CHAR (g), dp);
+             font_width = FRAME_COLUMN_WIDTH (f);
+             default_font = Fface_font (Qdefault, Qnil, Qnil);
+             frame_font = Fframe_parameter (Qnil, Qfont);
+
+             if (STRINGP (default_font) && STRINGP (frame_font)
+                 && (SCHARS (default_font) != SCHARS (frame_font)
+                     || SBYTES (default_font) != SBYTES (frame_font)
+                     || memcmp (SDATA (default_font), SDATA (frame_font),
+                                SBYTES (default_font))))
+               {
+                 Lisp_Object font_info = Ffont_info (default_font, Qnil);
+                 font_width = AREF (font_info, 11);
+                 if (font_info <= 0)
+                   font_width = AREF (font_info, 10);
+               }
            }
+         thiswidth = (double) pixelwidth / font_width + 0.5;
          chars = end - i;
          bytes = string_char_to_byte (string, end) - i_byte;
        }
+#endif /* HAVE_WINDOW_SYSTEM */
       else
        {
          int c;



reply via email to

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