Posted to tcl by hypnotoad at Fri Nov 30 23:36:05 GMT 2018view raw

  1. ###
  2. # Adapting from
  3. # https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
  4. # and
  5. # https://github.com/jquast/wcwidth/blob/master/wcwidth/wcwidth.py
  6. # to work in pure tcl
  7. ###
  8. namespace eval ::wcswidth {
  9. set ::wcswidth::ranges(0) {}
  10. set ::wcswidth::ranges(-1) {}
  11. set ::wcswidth::ranges(2) {}
  12.  
  13. foreach {length start end} {
  14. 0 0 0 -1 1 31 -1 0x7f 0xbf
  15. 0 0x0300 0x036F 0 0x0483 0x0486 0 0x0488 0x0489
  16. 0 0x0591 0x05BD 0 0x05BF 0x05BF 0 0x05C1 0x05C2
  17. 0 0x05C4 0x05C5 0 0x05C7 0x05C7 0 0x0600 0x0603
  18. 0 0x0610 0x0615 0 0x064B 0x065E 0 0x0670 0x0670
  19. 0 0x06D6 0x06E4 0 0x06E7 0x06E8 0 0x06EA 0x06ED
  20. 0 0x070F 0x070F 0 0x0711 0x0711 0 0x0730 0x074A
  21. 0 0x07A6 0x07B0 0 0x07EB 0x07F3 0 0x0901 0x0902
  22. 0 0x093C 0x093C 0 0x0941 0x0948 0 0x094D 0x094D
  23. 0 0x0951 0x0954 0 0x0962 0x0963 0 0x0981 0x0981
  24. 0 0x09BC 0x09BC 0 0x09C1 0x09C4 0 0x09CD 0x09CD
  25. 0 0x09E2 0x09E3 0 0x0A01 0x0A02 0 0x0A3C 0x0A3C
  26. 0 0x0A41 0x0A42 0 0x0A47 0x0A48 0 0x0A4B 0x0A4D
  27. 0 0x0A70 0x0A71 0 0x0A81 0x0A82 0 0x0ABC 0x0ABC
  28. 0 0x0AC1 0x0AC5 0 0x0AC7 0x0AC8 0 0x0ACD 0x0ACD
  29. 0 0x0AE2 0x0AE3 0 0x0B01 0x0B01 0 0x0B3C 0x0B3C
  30. 0 0x0B3F 0x0B3F 0 0x0B41 0x0B43 0 0x0B4D 0x0B4D
  31. 0 0x0B56 0x0B56 0 0x0B82 0x0B82 0 0x0BC0 0x0BC0
  32. 0 0x0BCD 0x0BCD 0 0x0C3E 0x0C40 0 0x0C46 0x0C48
  33. 0 0x0C4A 0x0C4D 0 0x0C55 0x0C56 0 0x0CBC 0x0CBC
  34. 0 0x0CBF 0x0CBF 0 0x0CC6 0x0CC6 0 0x0CCC 0x0CCD
  35. 0 0x0CE2 0x0CE3 0 0x0D41 0x0D43 0 0x0D4D 0x0D4D
  36. 0 0x0DCA 0x0DCA 0 0x0DD2 0x0DD4 0 0x0DD6 0x0DD6
  37. 0 0x0E31 0x0E31 0 0x0E34 0x0E3A 0 0x0E47 0x0E4E
  38. 0 0x0EB1 0x0EB1 0 0x0EB4 0x0EB9 0 0x0EBB 0x0EBC
  39. 0 0x0EC8 0x0ECD 0 0x0F18 0x0F19 0 0x0F35 0x0F35
  40. 0 0x0F37 0x0F37 0 0x0F39 0x0F39 0 0x0F71 0x0F7E
  41. 0 0x0F80 0x0F84 0 0x0F86 0x0F87 0 0x0F90 0x0F97
  42. 0 0x0F99 0x0FBC 0 0x0FC6 0x0FC6 0 0x102D 0x1030
  43. 0 0x1032 0x1032 0 0x1036 0x1037 0 0x1039 0x1039
  44. 0 0x1058 0x1059 0 0x1160 0x11FF 0 0x135F 0x135F
  45. 0 0x1712 0x1714 0 0x1732 0x1734 0 0x1752 0x1753
  46. 0 0x1772 0x1773 0 0x17B4 0x17B5 0 0x17B7 0x17BD
  47. 0 0x17C6 0x17C6 0 0x17C9 0x17D3 0 0x17DD 0x17DD
  48. 0 0x180B 0x180D 0 0x18A9 0x18A9 0 0x1920 0x1922
  49. 0 0x1927 0x1928 0 0x1932 0x1932 0 0x1939 0x193B
  50. 0 0x1A17 0x1A18 0 0x1B00 0x1B03 0 0x1B34 0x1B34
  51. 0 0x1B36 0x1B3A 0 0x1B3C 0x1B3C 0 0x1B42 0x1B42
  52. 0 0x1B6B 0x1B73 0 0x1DC0 0x1DCA 0 0x1DFE 0x1DFF
  53. 0 0x200B 0x200F 0 0x202A 0x202E 0 0x2060 0x2063
  54. 0 0x206A 0x206F 0 0x20D0 0x20EF 0 0x302A 0x302F
  55. 0 0x3099 0x309A 0 0xA806 0xA806 0 0xA80B 0xA80B
  56. 0 0xA825 0xA826 0 0xFB1E 0xFB1E 0 0xFE00 0xFE0F
  57. 0 0xFE20 0xFE23 0 0xFEFF 0xFEFF 0 0xFFF9 0xFFFB
  58. 0 0x10A01 0x10A03 0 0x10A05 0x10A06 0 0x10A0C 0x10A0F
  59. 0 0x10A38 0x10A3A 0 0x10A3F 0x10A3F 0 0x1D167 0x1D169
  60. 0 0x1D173 0x1D182 0 0x1D185 0x1D18B 0 0x1D1AA 0x1D1AD
  61. 0 0x1D242 0x1D244 0 0xE0001 0xE0001 0 0xE0020 0xE007F
  62. 0 0xE0100 0xE01EF
  63. } {
  64. lappend ::wcswidth::ranges($length) $start $end
  65. }
  66.  
  67. foreach {start end comment} {
  68. 0x1100 0x115f {CJK ... Yi}
  69. 0x2329 0x2329 {Hangul Jamo init. consonant}
  70. 0x232a 0x232a {Hangul Jamo init. consonant}
  71. 0x2e80 0x303e {CJK ... Yi}
  72. 0x3040 0xa4cf {CJK ... Yi}
  73. 0xac00 0xd7a3 {Hangul Syllables}
  74. 0xf900 0xfaff {CJK Compatibility Ideographs}
  75. 0xfe10 0xfe19 {Vertical forms}
  76. 0xfe30 0xfe6f {CJK Compatibility Forms}
  77. 0xff00 0xff60 {Fullwidth Forms}
  78. 0xffe0 0xffe6 {Fullwidth Forms}
  79. 0x20000 0x2fffd {Fullwidth Forms}
  80. 0x30000 0x3fffd {Fullwidth Forms}
  81. } {
  82. lappend ::wcswidth::ranges(2) $start $end
  83. }
  84. }
  85. proc ::wcswidth::charwidth {char} {
  86. variable ranges
  87. foreach width {-1 0 2} {
  88. foreach {start end} $ranges($width) {
  89. if {$char >= $start && $char <= $end} {
  90. return $width
  91. }
  92. }
  93. }
  94. return 1
  95. }
  96.  
  97. proc wcswidth {string} {
  98. set width 0
  99. set len [string length $string]
  100. for {set i 0} {$i < $len} {incr i} {
  101. scan [string index $string $i] %c char
  102. set n [::wcswidth::charwidth $char]
  103. if {$n < 0} {
  104. return -1
  105. }
  106. incr width $n
  107. }
  108. return $width
  109. }
  110.