11cb0ef41Sopenharmony_ci"use strict"
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_civar defaults = require('defaults')
41cb0ef41Sopenharmony_civar combining = require('./combining')
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_civar DEFAULTS = {
71cb0ef41Sopenharmony_ci  nul: 0,
81cb0ef41Sopenharmony_ci  control: 0
91cb0ef41Sopenharmony_ci}
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cimodule.exports = function wcwidth(str) {
121cb0ef41Sopenharmony_ci  return wcswidth(str, DEFAULTS)
131cb0ef41Sopenharmony_ci}
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cimodule.exports.config = function(opts) {
161cb0ef41Sopenharmony_ci  opts = defaults(opts || {}, DEFAULTS)
171cb0ef41Sopenharmony_ci  return function wcwidth(str) {
181cb0ef41Sopenharmony_ci    return wcswidth(str, opts)
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci}
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci/*
231cb0ef41Sopenharmony_ci *  The following functions define the column width of an ISO 10646
241cb0ef41Sopenharmony_ci *  character as follows:
251cb0ef41Sopenharmony_ci *  - The null character (U+0000) has a column width of 0.
261cb0ef41Sopenharmony_ci *  - Other C0/C1 control characters and DEL will lead to a return value
271cb0ef41Sopenharmony_ci *    of -1.
281cb0ef41Sopenharmony_ci *  - Non-spacing and enclosing combining characters (general category
291cb0ef41Sopenharmony_ci *    code Mn or Me in the
301cb0ef41Sopenharmony_ci *    Unicode database) have a column width of 0.
311cb0ef41Sopenharmony_ci *  - SOFT HYPHEN (U+00AD) has a column width of 1.
321cb0ef41Sopenharmony_ci *  - Other format characters (general category code Cf in the Unicode
331cb0ef41Sopenharmony_ci *    database) and ZERO WIDTH
341cb0ef41Sopenharmony_ci *    SPACE (U+200B) have a column width of 0.
351cb0ef41Sopenharmony_ci *  - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
361cb0ef41Sopenharmony_ci *    have a column width of 0.
371cb0ef41Sopenharmony_ci *  - Spacing characters in the East Asian Wide (W) or East Asian
381cb0ef41Sopenharmony_ci *    Full-width (F) category as
391cb0ef41Sopenharmony_ci *    defined in Unicode Technical Report #11 have a column width of 2.
401cb0ef41Sopenharmony_ci *  - All remaining characters (including all printable ISO 8859-1 and
411cb0ef41Sopenharmony_ci *    WGL4 characters, Unicode control characters, etc.) have a column
421cb0ef41Sopenharmony_ci *    width of 1.
431cb0ef41Sopenharmony_ci *  This implementation assumes that characters are encoded in ISO 10646.
441cb0ef41Sopenharmony_ci*/
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_cifunction wcswidth(str, opts) {
471cb0ef41Sopenharmony_ci  if (typeof str !== 'string') return wcwidth(str, opts)
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  var s = 0
501cb0ef41Sopenharmony_ci  for (var i = 0; i < str.length; i++) {
511cb0ef41Sopenharmony_ci    var n = wcwidth(str.charCodeAt(i), opts)
521cb0ef41Sopenharmony_ci    if (n < 0) return -1
531cb0ef41Sopenharmony_ci    s += n
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  return s
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_cifunction wcwidth(ucs, opts) {
601cb0ef41Sopenharmony_ci  // test for 8-bit control characters
611cb0ef41Sopenharmony_ci  if (ucs === 0) return opts.nul
621cb0ef41Sopenharmony_ci  if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return opts.control
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  // binary search in table of non-spacing characters
651cb0ef41Sopenharmony_ci  if (bisearch(ucs)) return 0
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  // if we arrive here, ucs is not a combining or C0/C1 control character
681cb0ef41Sopenharmony_ci  return 1 +
691cb0ef41Sopenharmony_ci      (ucs >= 0x1100 &&
701cb0ef41Sopenharmony_ci       (ucs <= 0x115f ||                       // Hangul Jamo init. consonants
711cb0ef41Sopenharmony_ci        ucs == 0x2329 || ucs == 0x232a ||
721cb0ef41Sopenharmony_ci        (ucs >= 0x2e80 && ucs <= 0xa4cf &&
731cb0ef41Sopenharmony_ci         ucs != 0x303f) ||                     // CJK ... Yi
741cb0ef41Sopenharmony_ci        (ucs >= 0xac00 && ucs <= 0xd7a3) ||    // Hangul Syllables
751cb0ef41Sopenharmony_ci        (ucs >= 0xf900 && ucs <= 0xfaff) ||    // CJK Compatibility Ideographs
761cb0ef41Sopenharmony_ci        (ucs >= 0xfe10 && ucs <= 0xfe19) ||    // Vertical forms
771cb0ef41Sopenharmony_ci        (ucs >= 0xfe30 && ucs <= 0xfe6f) ||    // CJK Compatibility Forms
781cb0ef41Sopenharmony_ci        (ucs >= 0xff00 && ucs <= 0xff60) ||    // Fullwidth Forms
791cb0ef41Sopenharmony_ci        (ucs >= 0xffe0 && ucs <= 0xffe6) ||
801cb0ef41Sopenharmony_ci        (ucs >= 0x20000 && ucs <= 0x2fffd) ||
811cb0ef41Sopenharmony_ci        (ucs >= 0x30000 && ucs <= 0x3fffd)));
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_cifunction bisearch(ucs) {
851cb0ef41Sopenharmony_ci  var min = 0
861cb0ef41Sopenharmony_ci  var max = combining.length - 1
871cb0ef41Sopenharmony_ci  var mid
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  if (ucs < combining[0][0] || ucs > combining[max][1]) return false
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  while (max >= min) {
921cb0ef41Sopenharmony_ci    mid = Math.floor((min + max) / 2)
931cb0ef41Sopenharmony_ci    if (ucs > combining[mid][1]) min = mid + 1
941cb0ef41Sopenharmony_ci    else if (ucs < combining[mid][0]) max = mid - 1
951cb0ef41Sopenharmony_ci    else return true
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  return false
991cb0ef41Sopenharmony_ci}
100