Subject: bug#64420: string-width of … is 2 in CJK environments

From: Eli Zaretskii <[email-masked]>
Date: Sun, 02 Jul 2023 16:43:04 +0300

> Date: Sun, 2 Jul 2023 16:20:25 +0300
> Cc: [email-masked]
> From: Dmitry Gutov <[email-masked]>
> 
> > On GUI frames Lisp programs that need to know the actual width of some
> > string should use string-pixel-width, not string-width.  The latter is
> > basically only for TTY frames.
> > 
> >     (progn
> >       (set-language-environment "Chinese-BIG5")
> >       (ceiling (/ (string-pixel-width "…")
> >                   (float (default-font-width))))) ;; => 1
> 
> Thank you.
> 
> Is there some inherent reason why string-width differs from the result 
> of the above expression

Because string-width doesn't consult the actual metrics of the font.
It uses a char-table that we set "by hand".

> and especially only does that on CJK?

In CJK locales, most characters are double-width because those locales
use fonts where the glyphs are wider.  Or at least this is the theory.
string-pixel-width is free from these assumptions because it actually
measures the font glyphs.

> Since the overlay-based popup is used on both GUI and Terminal frames, 
> are you suggesting I define my own string-width like this?
> 
> (defun company--string-width (str)
>    (if (display-graphic-p)
>        (ceiling (/ (string-pixel-width str)
>                    (float (default-font-width))))
>      (string-width str)))

Yes, definitely.  (Actually, display-multi-font-p is better than
display-graphic-p, but in practice they will return the same value.)