Fix box misalignment for emoji with variation selectors#133
Conversation
Characters like⚠️ are actually two codepoints: the base symbol (⚠ U+26A0) plus an invisible "variation selector" (U+FE0F) that tells the terminal to render it as a wide emoji. Boxes counted the base symbol as 1 column wide and ignored the selector, but terminals display it as 2 columns. This made the right border shift 1 position too far for each affected character. Characters like 💡 that are inherently wide were handled correctly — only the ones that get promoted to wide by the variation selector were miscounted. Common affected characters:⚠️ , ℹ️, ✅, ❤️, 1⃣ and other keycap emoji.
|
Thank you for this contribution! It looks good at first glance, but I will need more time to properly review. For the next two or three weeks, I won't be able to do that. But after that, I'll get the review done and get back to you. |
|
Question (mostly to myself): Why does libunistring's One of us can ask their AI. 🙂 But it will be good to have this answer for the review. |
|
The root cause is certainly with libunistring, whose If it turns out that it's a proper bug but they can't fix it, then I'll merge this. Other possible futures are: They tell me how to invoke libunistring so we get the correct width, or they provide a 1.4.3 with a fix. |
|
Alright, we got a reply by @bhaible, the maintainer of libunistring! He explains that the specification for this case (WARNING SIGN + VS16) does not mandate a width of two characters, and also demonstrates that many renderers actually render it with a width of one. So you have officially discovered a gray area! It is unclear whether a width of 1 or 2 is formally correct, and renderers differ on this. For the sake of consistency, Bruno prefers to stay at 1, but he was open to changing that at some point in the future as more renderers come around to a width of 2. In my world, all renderers consistently use a width of 2. So, I'll now look at your contribution in more detail to get it merged. |
|
@forty Can you please rebase so that we get the complete CI? Thanks! |
Characters like⚠️ are actually two codepoints: the base symbol (⚠ U+26A0) plus an invisible "variation selector" (U+FE0F) that tells the terminal to render it as a wide emoji.
Boxes counted the base symbol as 1 column wide and ignored the selector, but terminals display it as 2 columns. This made the right border shift 1 position too far for each affected character.
Characters like 💡 that are inherently wide were handled correctly — only the ones that get promoted to wide by the variation selector were miscounted.
Common affected characters:⚠️ , ℹ️, ✅, ❤️, 1⃣ and other keycap emoji.
Disclaimer this MR was done with the help of "AI". Though I have carefully reviewed and amended the code and made sure it was tested correctly, I'm not a C developer nor a Unicode expert, just some guy with a an ascii box which was not aligned :)