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' .
This commit is contained in:
parent
7f11dea662
commit
c82afdcc88
1 changed files with 34 additions and 8 deletions
|
@ -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);
|
||||
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;
|
||||
|
|
Loading…
Add table
Reference in a new issue