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)