MCPcopy Create free account
hub / github.com/Genivia/ugrep / wchar_width

Method wchar_width

src/screen.cpp:345–426  ·  view source on GitHub ↗

return character display width, 0 (non-spacing or invalid character), 1 (single width) or 2 (double width)

Source from the content-addressed store, hash-verified

343
344// return character display width, 0 (non-spacing or invalid character), 1 (single width) or 2 (double width)
345int Screen::wchar_width(uint32_t wc)
346{
347 // ignore invisible characters, such as invalid UTF-8
348 if (wc == 0)
349 return 0;
350
351 // control characters are double width to display them e.g. as \t or ^I
352 if (wc < 0x20 || wc == 0x7f)
353 return 2;
354
355 /* Based on https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c with full table
356 generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c"
357 from https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
358 this is a compressed table of combining character ranges, stored as
359 range.first << 8 | (range.last - range.first)
360
361 We don't use wcwidth() because it is broken on some systems, e.g. MacOS
362 wcwidth(0x1f600) returns -1 for the emoticon U+1F600
363 */
364 static const uint32_t combining[] = {
365 0x3006f, 0x48303, 0x48801, 0x5912c, 0x5bf00, 0x5c101, 0x5c401, 0x5c700,
366 0x60003, 0x61005, 0x64b13, 0x67000, 0x6d60e, 0x6e701, 0x6ea03, 0x70f00,
367 0x71100, 0x7301a, 0x7a60a, 0x7eb08, 0x90101, 0x93c00, 0x94107, 0x94d00,
368 0x95103, 0x96201, 0x98100, 0x9bc00, 0x9c103, 0x9cd00, 0x9e201, 0xa0101,
369 0xa3c00, 0xa4101, 0xa4701, 0xa4b02, 0xa7001, 0xa8101, 0xabc00, 0xac104,
370 0xac701, 0xacd00, 0xae201, 0xb0100, 0xb3c00, 0xb3f00, 0xb4102, 0xb4d00,
371 0xb5600, 0xb8200, 0xbc000, 0xbcd00, 0xc3e02, 0xc4602, 0xc4a03, 0xc5501,
372 0xcbc00, 0xcbf00, 0xcc600, 0xccc01, 0xce201, 0xd4102, 0xd4d00, 0xdca00,
373 0xdd202, 0xdd600, 0xe3100, 0xe3406, 0xe4707, 0xeb100, 0xeb405, 0xebb01,
374 0xec805, 0xf1801, 0xf3500, 0xf3700, 0xf3900, 0xf710d, 0xf8004, 0xf8601,
375 0xf9007, 0xf9923, 0xfc600,
376 0x102d03, 0x103200, 0x103601, 0x103900, 0x105801, 0x11609f, 0x135f00,
377 0x171202, 0x173202, 0x175201, 0x177201, 0x17b401, 0x17b706, 0x17c600,
378 0x17c90a, 0x17dd00, 0x180b02, 0x18a900, 0x192002, 0x192701, 0x193200,
379 0x193902, 0x1a1701, 0x1b0003, 0x1b3400, 0x1b3604, 0x1b3c00, 0x1b4200,
380 0x1b6b08, 0x1dc00a, 0x1dfe01, 0x200b04, 0x202a04, 0x206003, 0x206a05,
381 0x20d01f, 0x302a05, 0x309901, 0xa80600, 0xa80b00, 0xa82501, 0xfb1e00,
382 0xfe000f, 0xfe2003, 0xfeff00, 0xfff902,
383 0x10a0102, 0x10a0501, 0x10a0c03, 0x10a3802, 0x10a3f00, 0x1d16702, 0x1d1730f,
384 0x1d18506, 0x1d1aa03, 0x1d24202, 0xe000100, 0xe00205f, 0xe0100ef,
385 };
386
387 int min = 0;
388 int max = sizeof(combining) / sizeof(uint32_t) - 1;
389
390 // binary search in table of non-spacing characters
391 if (wc >= (combining[0] >> 8) && wc <= (combining[max] >> 8) + (combining[max] & 0xff))
392 {
393 while (max >= min)
394 {
395 int mid = (min + max) / 2;
396 if (wc < (combining[mid] >> 8))
397 max = mid - 1;
398 else if (wc > (combining[mid] >> 8) + (combining[mid] & 0xff))
399 min = mid + 1;
400 else
401 return 0;
402 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected