diff --git a/src/character.c b/src/character.c index e0978bb39fa..5753e883c32 100644 --- a/src/character.c +++ b/src/character.c @@ -34,6 +34,7 @@ along with GNU Emacs. If not, see . */ #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); + font_width = FRAME_COLUMN_WIDTH (f); + default_font = Fface_font (Qdefault, Qnil, Qnil); + frame_font = Fframe_parameter (Qnil, Qfont); - if (NILP (g)) - break; - thiswidth += char_width (LGLYPH_CHAR (g), dp); + 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;