runeWidth function

int runeWidth(
  1. int rune
)

Returns the display width of a single Unicode code point.

Control characters, combining marks, and zero-width characters return 0. CJK, fullwidth, and emoji characters return 2. All others return 1.

Implementation

int runeWidth(int rune) {
  // Control characters and null
  if (rune < 32 || (rune >= 0x7F && rune < 0xA0)) {
    return 0;
  }

  // Combining characters (zero width)
  if ((rune >= 0x0300 && rune <= 0x036F) || // Combining Diacritical Marks
      (rune >= 0x1AB0 &&
          rune <= 0x1AFF) || // Combining Diacritical Marks Extended
      (rune >= 0x1DC0 &&
          rune <= 0x1DFF) || // Combining Diacritical Marks Supplement
      (rune >= 0x20D0 &&
          rune <= 0x20FF) || // Combining Diacritical Marks for Symbols
      (rune >= 0xFE20 && rune <= 0xFE2F)) {
    // Combining Half Marks
    return 0;
  }

  // Zero-width (very small subset).
  if (rune == 0x200B || // ZWSP
      rune == 0x200C || // ZWNJ
      rune == 0x200D || // ZWJ
      rune == 0xFEFF || // BOM
      (rune >= 0xFE00 && rune <= 0xFE0F) || // Variation Selectors (VS1-VS16)
      (rune >= 0xE0100 && rune <= 0xE01EF)) {
    // Variation Selectors Supplement (VS17-VS256)
    return 0;
  }

  // Wide characters (CJK + emoji range subset).
  if ((rune >= 0x1100 && rune <= 0x115F) || // Hangul Jamo
      (rune >= 0x2E80 && rune <= 0x9FFF) || // CJK
      (rune >= 0xAC00 && rune <= 0xD7A3) || // Hangul Syllables
      (rune >= 0xF900 && rune <= 0xFAFF) || // CJK Compatibility
      (rune >= 0xFE10 && rune <= 0xFE1F) || // Vertical Forms
      (rune >= 0xFE30 && rune <= 0xFE6F) || // CJK Compatibility Forms
      (rune >= 0xFF00 && rune <= 0xFF60) || // Fullwidth ASCII
      (rune >= 0xFFE0 && rune <= 0xFFE6) || // Fullwidth symbols
      (rune >= 0x20000 && rune <= 0x3FFFF)) {
    return 2;
  }

  // Emoji / symbol characters that terminals render as wide (2 cells).
  // These are below U+2E80 (the CJK range start) but have emoji presentation
  // in most terminals.
  if (_isEmojiPresentation(rune)) {
    return emojiPresentationWidth;
  }

  // Emoji ranges in Supplementary Multilingual Plane (U+1Fxxx).
  // Covers all Emoji_Presentation=Yes code points above U+FFFF.
  // Source: Unicode Emoji Data 15.1 — emoji-data.txt
  if ((rune >= 0x1F000 && rune <= 0x1F02F) || // Mahjong Tiles, Dominos
      (rune >= 0x1F0A0 && rune <= 0x1F0FF) || // Playing Cards
      (rune >= 0x1F100 &&
          rune <= 0x1F1FF) || // Enclosed Alphanumerics + Regional Indicators
      (rune >= 0x1F200 && rune <= 0x1F2FF) || // Enclosed Ideographic Supplement
      (rune >= 0x1F300 &&
          rune <= 0x1F9FF) || // Misc Symbols/Pictographs, Emoticons, etc.
      (rune >= 0x1FA00 &&
          rune <= 0x1FAFF) || // Symbols and Pictographs Extended-A
      (rune >= 0x1F7E0 && rune <= 0x1F7FF)) {
    // Geometric Shapes Extended (colored circles/squares)
    return emojiPresentationWidth;
  }

  return 1;
}