2 * This is an implementation of wcwidth() and wcswidth() as defined in
3 * "The Single UNIX Specification, Version 2, The Open Group, 1997"
4 * <http://www.UNIX-systems.org/online.html>
6 * Markus Kuhn -- 2000-02-08 -- public domain
11 /* These functions define the column width of an ISO 10646 character
14 * - The null character (U+0000) has a column width of 0.
16 * - Other C0/C1 control characters and DEL will lead to a return
19 * - Non-spacing and enclosing combining characters (general
20 * category code Mn or Me in the Unicode database) have a
23 * - Spacing characters in the East Asian Wide (W) or East Asian
24 * FullWidth (F) category as defined in Unicode Technical
25 * Report #11 have a column width of 2.
27 * - All remaining characters (including all printable
28 * ISO 8859-1 and WGL4 characters, Unicode control characters,
29 * etc.) have a column width of 1.
31 * This implementation assumes that wchar_t characters are encoded
35 int wcwidth(wchar_t ucs
)
37 /* sorted list of non-overlapping intervals of non-spacing characters */
38 static const struct interval
{
137 int max
= sizeof(combining
) / sizeof(struct interval
) - 1;
140 /* test for 8-bit control characters */
143 if (ucs
< 32 || (ucs
>= 0x7f && ucs
< 0xa0))
146 /* first quick check for Latin-1 etc. characters */
147 if (ucs
< combining
[0].first
)
150 /* binary search in table of non-spacing characters */
152 mid
= (min
+ max
) / 2;
153 if (combining
[mid
].last
< ucs
)
155 else if (combining
[mid
].first
> ucs
)
157 else if (combining
[mid
].first
<= ucs
&& combining
[mid
].last
>= ucs
)
161 /* if we arrive here, ucs is not a combining or C0/C1 control character */
163 /* fast test for majority of non-wide scripts */
167 return 1 + ((ucs
>= 0x1100 && ucs
<= 0x115f) || /* Hangul Jamo */
169 (ucs
>= 0x2e80 && ucs
<= 0xa4cf
170 && (ucs
& ~0x0011) != 0x300a && ucs
!= 0x303f) || /* CJK ... Yi */
171 (ucs
>= 0xac00 && ucs
<= 0xd7a3) || /* Hangul Syllables */
172 (ucs
>= 0xf900 && ucs
<= 0xfaff) || /* CJK Compatibility Ideographs */
173 (ucs
>= 0xfe30 && ucs
<= 0xfe6f) || /* CJK Compatibility Forms */
174 (ucs
>= 0xff00 && ucs
<= 0xff5f) || /* Fullwidth Forms */
175 (ucs
>= 0xffe0 && ucs
<= 0xffe6));
179 int wcswidth(const wchar_t * pwcs
, size_t n
)
183 for (; *pwcs
&& n
-- > 0; pwcs
++)
184 if ((w
= wcwidth(*pwcs
)) < 0)