whole_func_string: function _resolveCharType(chars, types, resolvedTypes, index) {
        var cType = types[index],
            wType,
            nType,
            i,
            len;
  
        switch (cType) {
          case "L":
          case "R":
            _lastArabic = false;
            break;
  
          case "N":
          case "AN":
            break;
  
          case "EN":
            if (_lastArabic) {
              cType = "AN";
            }
  
            break;
  
          case "AL":
            _lastArabic = true;
            cType = "R";
            break;
  
          case "WS":
            cType = "N";
            break;
  
          case "CS":
            if (index < 1 || index + 1 >= types.length || (wType = resolvedTypes[index - 1]) !== "EN" && wType !== "AN" || (nType = types[index + 1]) !== "EN" && nType !== "AN") {
              cType = "N";
            } else if (_lastArabic) {
              nType = "AN";
            }
  
            cType = nType === wType ? nType : "N";
            break;
  
          case "ES":
            wType = index > 0 ? resolvedTypes[index - 1] : "B";
            cType = wType === "EN" && index + 1 < types.length && types[index + 1] === "EN" ? "EN" : "N";
            break;
  
          case "ET":
            if (index > 0 && resolvedTypes[index - 1] === "EN") {
              cType = "EN";
              break;
            } else if (_lastArabic) {
              cType = "N";
              break;
            }
  
            i = index + 1;
            len = types.length;
  
            while (i < len && types[i] === "ET") {
              i++;
            }
  
            if (i < len && types[i] === "EN") {
              cType = "EN";
            } else {
              cType = "N";
            }
  
            break;
  
          case "NSM":
            if (_isInVisual && !_isInRtl) {
              //V->L
              len = types.length;
              i = index + 1;
  
              while (i < len && types[i] === "NSM") {
                i++;
              }
  
              if (i < len) {
                var c = chars[index];
                var rtlCandidate = c >= 0x0591 && c <= 0x08FF || c === 0xFB1E;
                wType = types[i];
  
                if (rtlCandidate && (wType === "R" || wType === "AL")) {
                  cType = "R";
                  break;
                }
              }
            }
  
            if (index < 1 || (wType = types[index - 1]) === "B") {
              cType = "N";
            } else {
              cType = resolvedTypes[index - 1];
            }
  
            break;
  
          case "B":
            _lastArabic = false;
            _hasUbatB = true;
            cType = _dir;
            break;
  
          case "S":
            _hasUbatS = true;
            cType = "N";
            break;
  
          case "LRE":
          case "RLE":
          case "LRO":
          case "RLO":
          case "PDF":
            _lastArabic = false;
            break;
  
          case "BN":
            cType = "N";
            break;
        }
  
        return cType;
      }
func_code_string: function _resolveCharType(chars, types, resolvedTypes, index) {
        var cType = types[index],
            wType,
            nType,
            i,
            len;
  
        switch (cType) {
          case "L":
          case "R":
            _lastArabic = false;
            break;
  
          case "N":
          case "AN":
            break;
  
          case "EN":
            if (_lastArabic) {
              cType = "AN";
            }
  
            break;
  
          case "AL":
            _lastArabic = true;
            cType = "R";
            break;
  
          case "WS":
            cType = "N";
            break;
  
          case "CS":
            if (index < 1 || index + 1 >= types.length || (wType = resolvedTypes[index - 1]) !== "EN" && wType !== "AN" || (nType = types[index + 1]) !== "EN" && nType !== "AN") {
              cType = "N";
            } else if (_lastArabic) {
              nType = "AN";
            }
  
            cType = nType === wType ? nType : "N";
            break;
  
          case "ES":
            wType = index > 0 ? resolvedTypes[index - 1] : "B";
            cType = wType === "EN" && index + 1 < types.length && types[index + 1] === "EN" ? "EN" : "N";
            break;
  
          case "ET":
            if (index > 0 && resolvedTypes[index - 1] === "EN") {
              cType = "EN";
              break;
            } else if (_lastArabic) {
              cType = "N";
              break;
            }
  
            i = index + 1;
            len = types.length;
  
            while (i < len && types[i] === "ET") {
              i++;
            }
  
            if (i < len && types[i] === "EN") {
              cType = "EN";
            } else {
              cType = "N";
            }
  
            break;
  
          case "NSM":
            if (_isInVisual && !_isInRtl) {
              //V->L
              len = types.length;
              i = index + 1;
  
              while (i < len && types[i] === "NSM") {
                i++;
              }
  
              if (i < len) {
                var c = chars[index];
                var rtlCandidate = c >= 0x0591 && c <= 0x08FF || c === 0xFB1E;
                wType = types[i];
  
                if (rtlCandidate && (wType === "R" || wType === "AL")) {
                  cType = "R";
                  break;
                }
              }
            }
  
            if (index < 1 || (wType = types[index - 1]) === "B") {
              cType = "N";
            } else {
              cType = resolvedTypes[index - 1];
            }
  
            break;
  
          case "B":
            _lastArabic = false;
            _hasUbatB = true;
            cType = _dir;
            break;
  
          case "S":
            _hasUbatS = true;
            cType = "N";
            break;
  
          case "LRE":
          case "RLE":
          case "LRO":
          case "RLO":
          case "PDF":
            _lastArabic = false;
            break;
  
          case "BN":
            cType = "N";
            break;
        }
  
        return cType;
      }
func_documentation_string: for reference see 3.3.4 & 3.3.5 in http://unicode.org/reports/tr9/