[READ-ONLY] Mirror of https://github.com/bombshell-dev/tty. Platform independent 2D layout engine for terminal applications based on Clay
5

Configure Feed

Select the types of activity you want to include in your feed.

ref(wcwidth): regen

Nate Moore (Jul 2, 2026, 12:16 AM EDT) 579d2f6f 4195290e

+92 -61
+92 -61
src/wcwidth.c
··· 1 1 /* wcwidth.c - Unicode character width lookup 2 2 * Unicode 16.0 - generated by tasks/gen-wcwidth.ts 3 - * Data hash: 2397fe3ee973c18a 3 + * Data hash: d73f21ced2426cb4 4 4 * 5 5 * Only zero-width (combining marks + default ignorable) and double-width 6 6 * (wide/fullwidth) codepoints are stored. Everything else defaults to ··· 12 12 * DerivedCoreProperties.txt: Default_Ignorable_Code_Point -> width 0 13 13 * EastAsianWidth.txt: W/F properties -> width 2 14 14 * 15 + * NOTE: U+00AD SOFT HYPHEN is Default_Ignorable but is emitted as width 1, 16 + * not 0: the 0xA0-0xFF fast path in wcwidth() returns 1 for the whole block. 17 + * This is intentional and matches musl and U+00AD's EastAsianWidth=Narrow. 18 + * 19 + * Noncharacters (U+FDD0-U+FDEF and U+nFFFE/U+nFFFF) return -1: they are 20 + * permanently unassigned and never printable. They cannot be stored in the 21 + * packed table (the width bit only encodes 0 vs 2), so wcwidth() handles them 22 + * with a dedicated guard. 23 + * 15 24 * Combining (width 0) and wide (width 2) ranges are merged into a single 16 25 * sorted table so wcwidth() needs only one binary search for any codepoint. 17 26 * ··· 28 37 * 29 38 * Large-range encoding (special_large_* parallel arrays): 30 39 * Used for ranges whose span exceeds 1023 codepoints. 40 + * 41 + * TUI box-drawing fast lane (BOX_DRAWING_END): 42 + * U+2500..BOX_DRAWING_END (box drawing, block elements, shading, geometric 43 + * shapes) are all width 1, so wcwidth() returns 1 for them without searching. 44 + * 45 + * Lookup order in codepoint_in_special(): box fast lane, then the large table 46 + * (CJK/Hangul/SIP/tags exit in ~3 comparisons), then the BMP coarse filter, 47 + * then the packed small-range binary search. 31 48 */ 32 49 33 50 #include <stdint.h> ··· 57 74 0x00842802, 0x00846800, 0x0084e800, 0x008800bd, 0x008af802, 0x009ae804, 0x00b89004, 0x00b99002, 58 75 0x00ba9002, 0x00bb9002, 0x00bda002, 0x00bdb80c, 0x00be3000, 0x00be4814, 0x00bee800, 0x00c05808, 59 76 0x00c42802, 0x00c54800, 0x00c90004, 0x00c93802, 0x00c99000, 0x00c9c804, 0x00d0b802, 0x00d0d800, 60 - 0x00d2b000, 0x00d2c00c, 0x00d30000, 0x00d31000, 0x00d3280e, 0x00d39812, 0x00d3f800, 0x00d5803c, 61 - 0x00d80006, 0x00d9a000, 0x00d9b008, 0x00d9e000, 0x00da1000, 0x00db5810, 0x00dc0002, 0x00dd1006, 62 - 0x00dd4002, 0x00dd5804, 0x00df3000, 0x00df4002, 0x00df6800, 0x00df7804, 0x00e1600e, 0x00e1b002, 63 - 0x00e68004, 0x00e6a018, 0x00e7100c, 0x00e76800, 0x00e7a000, 0x00e7c002, 0x00ee007e, 0x01005808, 64 - 0x01015008, 0x0103001e, 0x01068040, 0x0118d003, 0x01194803, 0x011f4807, 0x011f8001, 0x011f9801, 65 - 0x012fe803, 0x0130a003, 0x0131800f, 0x01324017, 0x0133f801, 0x0134500b, 0x01349801, 0x01350801, 66 - 0x01355003, 0x0135e803, 0x01362003, 0x01367001, 0x0136a001, 0x01375001, 0x01379003, 0x0137a801, 67 - 0x0137d001, 0x0137e801, 0x01382801, 0x01385003, 0x01394001, 0x013a6001, 0x013a7001, 0x013a9805, 68 - 0x013ab801, 0x013ca805, 0x013d8001, 0x013df801, 0x0158d803, 0x015a8001, 0x015aa801, 0x01677804, 69 - 0x016bf800, 0x016f003e, 0x01740033, 0x0174d8b1, 0x017801ab, 0x017f8073, 0x01815006, 0x01817021, 70 - 0x018208ab, 0x0184c802, 0x0184d8c9, 0x01882855, 0x01898865, 0x018b2000, 0x018b2853, 0x018c80ab, 71 - 0x018f785f, 0x0191004f, 0x0524806d, 0x05337806, 0x0533a012, 0x0534f002, 0x05378002, 0x05401000, 72 - 0x05403000, 0x05405800, 0x05412802, 0x05416000, 0x05462002, 0x05470022, 0x0547f800, 0x0549300e, 73 - 0x054a3814, 0x054b0039, 0x054c0004, 0x054d9800, 0x054db006, 0x054de002, 0x054f2800, 0x0551480a, 74 - 0x05518802, 0x0551a802, 0x05521800, 0x05526000, 0x0553e000, 0x05558000, 0x05559004, 0x0555b802, 75 - 0x0555f002, 0x05560800, 0x05576002, 0x0557b000, 0x055f2800, 0x055f4000, 0x055f6800, 0x07c803ff, 76 - 0x07d8f000, 0x07f0001e, 0x07f08013, 0x07f1001e, 0x07f18045, 0x07f2a025, 0x07f34007, 0x07f7f800, 77 - 0x07f808bf, 0x07fd0000, 0x07ff000d, 0x07ff8010, 0x080fe800, 0x08170000, 0x081bb008, 0x08500804, 78 - 0x08502802, 0x08506006, 0x0851c004, 0x0851f800, 0x08572802, 0x08692006, 0x086b4808, 0x08755802, 79 - 0x0877e006, 0x087a3014, 0x087c1006, 0x08800800, 0x0881c01c, 0x08838000, 0x08839802, 0x0883f804, 80 - 0x08859806, 0x0885c802, 0x08861000, 0x08880004, 0x08893808, 0x0889680e, 0x088b9800, 0x088c0002, 81 - 0x088db010, 0x088e4806, 0x088e7800, 0x08917804, 0x0891a000, 0x0891b002, 0x0891f000, 0x08920800, 82 - 0x0896f800, 0x0897180e, 0x08980002, 0x0899d802, 0x089a0000, 0x089b300c, 0x089b8008, 0x089dd80a, 83 - 0x089e7000, 0x089e8000, 0x089e9000, 0x089f0802, 0x08a1c00e, 0x08a21004, 0x08a23000, 0x08a2f000, 84 - 0x08a5980a, 0x08a5d000, 0x08a5f802, 0x08a61002, 0x08ad9006, 0x08ade002, 0x08adf802, 0x08aee002, 85 - 0x08b1980e, 0x08b1e800, 0x08b1f802, 0x08b55800, 0x08b56800, 0x08b5800a, 0x08b5b800, 0x08b8e800, 86 - 0x08b8f800, 0x08b91006, 0x08b93808, 0x08c17810, 0x08c1c802, 0x08c9d802, 0x08c9f000, 0x08ca1800, 87 - 0x08cea006, 0x08ced002, 0x08cf0000, 0x08d00812, 0x08d1980a, 0x08d1d806, 0x08d23800, 0x08d2880a, 88 - 0x08d2c804, 0x08d45018, 0x08d4c002, 0x08e1800c, 0x08e1c00a, 0x08e1f800, 0x08e4902a, 0x08e5500c, 89 - 0x08e59002, 0x08e5a802, 0x08e9880a, 0x08e9d000, 0x08e9e002, 0x08e9f80c, 0x08ea3800, 0x08ec8002, 90 - 0x08eca800, 0x08ecb800, 0x08f79802, 0x08f80002, 0x08f9b008, 0x08fa0000, 0x08fa1000, 0x08fad000, 91 - 0x09a20000, 0x09a2381c, 0x0b08f016, 0x0b096804, 0x0b578008, 0x0b59800c, 0x0b7a7800, 0x0b7c7806, 92 - 0x0b7f0007, 0x0b7f2000, 0x0b7f8003, 0x0c67f813, 0x0d7f8007, 0x0d7fa80d, 0x0d7fe803, 0x0d800245, 93 - 0x0d899001, 0x0d8a8005, 0x0d8aa801, 0x0d8b2007, 0x0d8b8317, 0x0de4e802, 0x0de50006, 0x0e78005a, 94 - 0x0e79802c, 0x0e8b3804, 0x0e8b981e, 0x0e8c280c, 0x0e8d5006, 0x0e921004, 0x0e9800ad, 0x0e9b002d, 95 - 0x0ed0006c, 0x0ed1d862, 0x0ed3a800, 0x0ed42000, 0x0ed4d808, 0x0ed5081c, 0x0f00000c, 0x0f004020, 96 - 0x0f00d80c, 0x0f011802, 0x0f013008, 0x0f047800, 0x0f09800c, 0x0f157000, 0x0f176006, 0x0f276006, 97 - 0x0f2f7002, 0x0f46800c, 0x0f4a200c, 0x0f802001, 0x0f867801, 0x0f8c7001, 0x0f8c8813, 0x0f900005, 98 - 0x0f908057, 0x0f920011, 0x0f928003, 0x0f93000b, 0x0f980041, 0x0f996811, 0x0f99b88b, 0x0f9bf02b, 99 - 0x0f9d0055, 0x0f9e7809, 0x0f9f0021, 0x0f9fa001, 0x0f9fc08d, 0x0fa20001, 0x0fa21175, 0x0fa7f87d, 100 - 0x0faa5807, 0x0faa802f, 0x0fabd001, 0x0faca803, 0x0fad2001, 0x0fafd8a9, 0x0fb4008b, 0x0fb66001, 101 - 0x0fb68005, 0x0fb6a805, 0x0fb6e007, 0x0fb75803, 0x0fb7a011, 0x0fbf0017, 0x0fbf8001, 0x0fc8605d, 102 - 0x0fc9e013, 0x0fca3971, 0x0fd38019, 0x0fd40013, 0x0fd4786f, 0x0fd6701d, 0x0fd6f815, 0x0fd78011, 77 + 0x00d2b000, 0x00d2c00c, 0x00d30000, 0x00d31000, 0x00d3280e, 0x00d39812, 0x00d3f800, 0x00d5805a, 78 + 0x00d70016, 0x00d80006, 0x00d9a000, 0x00d9b008, 0x00d9e000, 0x00da1000, 0x00db5810, 0x00dc0002, 79 + 0x00dd1006, 0x00dd4002, 0x00dd5804, 0x00df3000, 0x00df4002, 0x00df6800, 0x00df7804, 0x00e1600e, 80 + 0x00e1b002, 0x00e68004, 0x00e6a018, 0x00e7100c, 0x00e76800, 0x00e7a000, 0x00e7c002, 0x00ee007e, 81 + 0x01005808, 0x01015008, 0x0103001e, 0x01068040, 0x0118d003, 0x01194803, 0x011f4807, 0x011f8001, 82 + 0x011f9801, 0x012fe803, 0x0130a003, 0x0131800f, 0x01324017, 0x0133f801, 0x0134500b, 0x01349801, 83 + 0x01350801, 0x01355003, 0x0135e803, 0x01362003, 0x01367001, 0x0136a001, 0x01375001, 0x01379003, 84 + 0x0137a801, 0x0137d001, 0x0137e801, 0x01382801, 0x01385003, 0x01394001, 0x013a6001, 0x013a7001, 85 + 0x013a9805, 0x013ab801, 0x013ca805, 0x013d8001, 0x013df801, 0x0158d803, 0x015a8001, 0x015aa801, 86 + 0x01677804, 0x016bf800, 0x016f003e, 0x01740033, 0x0174d8b1, 0x017801ab, 0x017f8073, 0x01815006, 87 + 0x01817021, 0x018208ab, 0x0184c802, 0x0184d8c9, 0x01882855, 0x01898865, 0x018b2000, 0x018b2853, 88 + 0x018c80ab, 0x018f785f, 0x0191004f, 0x0524806d, 0x05337806, 0x0533a012, 0x0534f002, 0x05378002, 89 + 0x05401000, 0x05403000, 0x05405800, 0x05412802, 0x05416000, 0x05462002, 0x05470022, 0x0547f800, 90 + 0x0549300e, 0x054a3814, 0x054b0039, 0x054c0004, 0x054d9800, 0x054db006, 0x054de002, 0x054f2800, 91 + 0x0551480a, 0x05518802, 0x0551a802, 0x05521800, 0x05526000, 0x0553e000, 0x05558000, 0x05559004, 92 + 0x0555b802, 0x0555f002, 0x05560800, 0x05576002, 0x0557b000, 0x055f2800, 0x055f4000, 0x055f6800, 93 + 0x07c803ff, 0x07d8f000, 0x07f0001e, 0x07f08013, 0x07f1001e, 0x07f18045, 0x07f2a025, 0x07f34007, 94 + 0x07f7f800, 0x07f808bf, 0x07fd0000, 0x07ff000d, 0x07ff8010, 0x080fe800, 0x08170000, 0x081bb008, 95 + 0x08500804, 0x08502802, 0x08506006, 0x0851c004, 0x0851f800, 0x08572802, 0x08692006, 0x086b4808, 96 + 0x08755802, 0x0877d00a, 0x087a3014, 0x087c1006, 0x08800800, 0x0881c01c, 0x08838000, 0x08839802, 97 + 0x0883f804, 0x08859806, 0x0885c802, 0x08861000, 0x08880004, 0x08893808, 0x0889680e, 0x088b9800, 98 + 0x088c0002, 0x088db010, 0x088e4806, 0x088e7800, 0x08917804, 0x0891a000, 0x0891b002, 0x0891f000, 99 + 0x08920800, 0x0896f800, 0x0897180e, 0x08980002, 0x0899d802, 0x089a0000, 0x089b300c, 0x089b8008, 100 + 0x089dd80a, 0x089e7000, 0x089e8000, 0x089e9000, 0x089f0802, 0x08a1c00e, 0x08a21004, 0x08a23000, 101 + 0x08a2f000, 0x08a5980a, 0x08a5d000, 0x08a5f802, 0x08a61002, 0x08ad9006, 0x08ade002, 0x08adf802, 102 + 0x08aee002, 0x08b1980e, 0x08b1e800, 0x08b1f802, 0x08b55800, 0x08b56800, 0x08b5800a, 0x08b5b800, 103 + 0x08b8e800, 0x08b8f800, 0x08b91006, 0x08b93808, 0x08c17810, 0x08c1c802, 0x08c9d802, 0x08c9f000, 104 + 0x08ca1800, 0x08cea006, 0x08ced002, 0x08cf0000, 0x08d00812, 0x08d1980a, 0x08d1d806, 0x08d23800, 105 + 0x08d2880a, 0x08d2c804, 0x08d45018, 0x08d4c002, 0x08db0000, 0x08db1004, 0x08db3000, 0x08e1800c, 106 + 0x08e1c00a, 0x08e1f800, 0x08e4902a, 0x08e5500c, 0x08e59002, 0x08e5a802, 0x08e9880a, 0x08e9d000, 107 + 0x08e9e002, 0x08e9f80c, 0x08ea3800, 0x08ec8002, 0x08eca800, 0x08ecb800, 0x08f79802, 0x08f80002, 108 + 0x08f9b008, 0x08fa0000, 0x08fa1000, 0x08fad000, 0x09a20000, 0x09a2381c, 0x0b08f016, 0x0b096804, 109 + 0x0b578008, 0x0b59800c, 0x0b7a7800, 0x0b7c7806, 0x0b7f0007, 0x0b7f2000, 0x0b7f800d, 0x0c67f83f, 110 + 0x0c6c00e5, 0x0d7f8007, 0x0d7fa80d, 0x0d7fe803, 0x0d800245, 0x0d899001, 0x0d8a8005, 0x0d8aa801, 111 + 0x0d8b2007, 0x0d8b8317, 0x0de4e802, 0x0de50006, 0x0e78005a, 0x0e79802c, 0x0e8b3804, 0x0e8b981e, 112 + 0x0e8c280c, 0x0e8d5006, 0x0e921004, 0x0e9800ad, 0x0e9b002d, 0x0ed0006c, 0x0ed1d862, 0x0ed3a800, 113 + 0x0ed42000, 0x0ed4d808, 0x0ed5081c, 0x0f00000c, 0x0f004020, 0x0f00d80c, 0x0f011802, 0x0f013008, 114 + 0x0f047800, 0x0f09800c, 0x0f157000, 0x0f176006, 0x0f276006, 0x0f2f7002, 0x0f371800, 0x0f373000, 115 + 0x0f377002, 0x0f37a800, 0x0f46800c, 0x0f4a200c, 0x0f802001, 0x0f867801, 0x0f8c7001, 0x0f8c8813, 116 + 0x0f900005, 0x0f908057, 0x0f920011, 0x0f928003, 0x0f93000b, 0x0f980041, 0x0f996811, 0x0f99b88b, 117 + 0x0f9bf02b, 0x0f9d0055, 0x0f9e7809, 0x0f9f0021, 0x0f9fa001, 0x0f9fc08d, 0x0fa20001, 0x0fa21175, 118 + 0x0fa7f87d, 0x0faa5807, 0x0faa802f, 0x0fabd001, 0x0faca803, 0x0fad2001, 0x0fafd8a9, 0x0fb4008b, 119 + 0x0fb66001, 0x0fb68005, 0x0fb6a807, 0x0fb6e007, 0x0fb75803, 0x0fb7a011, 0x0fbf0017, 0x0fbf8001, 120 + 0x0fc8605d, 0x0fc9e013, 0x0fca3971, 0x0fd38019, 0x0fd40015, 0x0fd47071, 0x0fd64001, 0x0fd6681f, 121 + 0x0fd6f817, 0x0fd77813, 103 122 }; 104 - #define SPECIAL_SMALL_COUNT 480 123 + #define SPECIAL_SMALL_COUNT 490 105 124 106 125 static const uint32_t special_large_starts[] = { 107 - 0x00003250, 0x0000ac00, 0x00017000, 0x00018800, 0x00020000, 0x00030000, 0x000e0000, 126 + 0x00003250, 0x0000ac00, 0x00017000, 0x00020000, 0x00030000, 0x000e0000, 108 127 }; 109 128 static const uint16_t special_large_counts[] = { 110 - 0x723c, 0x2ba3, 0x17f7, 0x04d5, 0xfffd, 0xfffd, 0x0fff, 129 + 0x723c, 0x2ba3, 0x1cd5, 0xfffd, 0xfffd, 0x0fff, 111 130 }; 112 131 static const uint8_t special_large_widths[] = { 113 - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 132 + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 114 133 }; 115 - #define SPECIAL_LARGE_COUNT 7 134 + #define SPECIAL_LARGE_COUNT 6 135 + #define BOX_DRAWING_END 0x25fc 116 136 117 137 /* clang-format on */ 118 138 119 139 static int codepoint_in_special(uint32_t codepoint) { 140 + /* TUI fast lane: U+2500..BOX_DRAWING_END (box drawing, block elements, 141 + * shading, geometric shapes) are all width 1; skip the search. */ 142 + if (codepoint >= 0x2500 && codepoint <= BOX_DRAWING_END) 143 + return 1; 144 + /* Big contiguous blocks (CJK, Hangul, SIP, tag chars) live in the large 145 + * table - check it first so common ideographs exit in ~3 comparisons 146 + * instead of missing through all the small ranges. */ 147 + int left = 0, right = SPECIAL_LARGE_COUNT - 1; 148 + while (left <= right) { 149 + int mid = (left + right) / 2; 150 + if (codepoint < special_large_starts[mid]) 151 + right = mid - 1; 152 + else if (codepoint > special_large_starts[mid] + special_large_counts[mid]) 153 + left = mid + 1; 154 + else 155 + return special_large_widths[mid]; 156 + } 120 157 if (codepoint <= 0xffff) { 121 158 uint32_t block = codepoint >> 7; 122 159 if (!((bmp_filter[block >> 5] >> (block & 31u)) & 1u)) 123 160 return 1; 124 161 } 125 - int left = 0, right = SPECIAL_SMALL_COUNT - 1; 162 + left = 0; 163 + right = SPECIAL_SMALL_COUNT - 1; 126 164 while (left <= right) { 127 165 int mid = (left + right) / 2; 128 166 uint32_t entry = special_small_ranges[mid]; ··· 134 172 else 135 173 return (entry & 1) ? 2 : 0; 136 174 } 137 - left = 0; 138 - right = SPECIAL_LARGE_COUNT - 1; 139 - while (left <= right) { 140 - int mid = (left + right) / 2; 141 - if (codepoint < special_large_starts[mid]) 142 - right = mid - 1; 143 - else if (codepoint > special_large_starts[mid] + special_large_counts[mid]) 144 - left = mid + 1; 145 - else 146 - return special_large_widths[mid]; 147 - } 148 175 return 1; 149 176 } 150 177 ··· 155 182 return 1; 156 183 if (codepoint < 0x20 || (codepoint > 0x7e && codepoint < 0xa0)) 157 184 return codepoint == 0 ? 0 : -1; 185 + /* Noncharacters are permanently unassigned and never printable: 186 + * U+FDD0..U+FDEF and the last two codepoints of every plane (U+nFFFE/U+nFFFF). */ 187 + if ((codepoint & 0xfffe) == 0xfffe || (codepoint >= 0xfdd0 && codepoint <= 0xfdef)) 188 + return -1; 158 189 return codepoint_in_special(codepoint); 159 190 } 160 191